Rosetta 3.5
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
grid_functions.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 protocols/ligand_docking/grid_functions.cc
11 ///
12 /// @brief
13 /// @author Ian W. Davis
14 
15 
17 
18 #include <core/graph/Graph.hh>
23 #include <basic/Tracer.hh>
24 #include <numeric/random/random_permutation.hh>
25 #include <utility/vector1.hh>
26 
29 #include <core/pose/Pose.hh>
30 #include <utility/vector0.hh>
31 
32 
33 namespace protocols {
34 namespace ligand_docking {
35 
36 
37 static basic::Tracer TR("protocols.ligand_docking.grid_functions", basic::t_debug);
38 static numeric::random::RandomGenerator my_RG(810329); // <- Magic number, do not change it!!!
39 
40 
41 /// @details If score exceeds max_score, stop counting and return (faster).
42 /// Atoms that fall outside the grid are scored as zero.
43 //template<typename T>
45  core::grid::CartGrid<int> const & grid,
46  core::conformation::Residue const & rsd,
47  int max_score /*= 9999*/
48 )
49 {
50  int score = 0;
51  for(core::Size i = 1, i_end = rsd.nheavyatoms(); i <= i_end && score < max_score; ++i) {
52  core::Vector const & atom = rsd.xyz(i);
53  if( grid.is_in_grid( atom.x(), atom.y(), atom.z() ) ) {
54  score += grid.getValue( atom.x(), atom.y(), atom.z() );
55  }
56  }
57  TR << "Grid score: " << score << std::endl;
58  return score;
59 }
60 
61 
62 /// @details If rep exceeds max_rep, atr is likely to be incorrect.
64  core::grid::CartGrid<int> const & grid,
65  core::conformation::Residue const & rsd,
66  int & atr_out,
67  int & rep_out,
68  int max_rep /*= 9999*/
69 )
70 {
71  for(core::Size i = 1, i_end = rsd.nheavyatoms(); i <= i_end && rep_out <= max_rep; ++i) {
72  core::Vector const & atom = rsd.xyz(i);
73  if( grid.is_in_grid( atom.x(), atom.y(), atom.z() ) ) {
74  int val = grid.getValue( atom.x(), atom.y(), atom.z() );
75  if( val > 0 ) rep_out += val;
76  else atr_out += val;
77  }
78  }
79  TR << "Grid score rep=" << rep_out << " atr=" << atr_out << std::endl;
80 }
81 
82 /// @brief Sum the grid values for all heavy atoms in the residue
84  core::grid::CartGrid<int> const & grid,
85  core::pose::Pose const & pose,
86  core::Size begin,
87  core::Size const end,
88  int & atr_out, //< sum of negative grid values
89  int & rep_out, //< sum of positive grid values
90  int max_rep
91 ){
92  for(; begin <= end; ++begin){
93  core::conformation::Residue const & r= pose.residue(begin);
94  grid_score_atr_rep(grid, r, atr_out, rep_out, max_rep);
95  }
96 }
97 
98 std::pair<int, int> get_rb_atr_and_rep_scores(
99  core::grid::CartGrid<int> const & grid,
100  core::pose::Pose const & pose,
101  core::Size begin,
103 ){
104  int atr=0;
105  int rep=0;
106  rb_grid_score_atr_rep(grid, pose, begin, end, atr, rep);
107  return std::pair<int, int>(atr,rep);
108 }
109 
110 /// @details min_score exists so you can search for the rotamer that clashes with the grid
111 /// a minimal ammount instead of none, to disfavor free-floating, non-interacting poses.
113  core::grid::CartGrid<int> const & grid,
114  core::pose::Pose & pose,
115  core::Size rsd_no,
116  int const min_score /*= 0*/
117 )
118 {
120 
121  // Retrieve list of conformers
123  rotamers_for_trials(pose, rsd_no, conformers);
124  if( conformers.empty() ) return;
125  // Conformers are already aligned onto original residue coords at this point.
126 
127  // Select best conformer, stopping early if score == 0
128  int best_score = 9999;
129  core::Size best_i = 0;
130  for(core::Size i = 1, i_end = conformers.size(); i <= i_end; ++i) {
131  ResidueOP rsd = conformers[i];
132  int const new_score = grid_score(grid, *rsd, best_score);
133  if( new_score < best_score && new_score >= min_score ) {
134  best_score = new_score;
135  best_i = i;
136  if(best_score == min_score) break;
137  }
138  }
139 
140  // Replace current residue with best residue
141  if( best_i > 0 ) {
142  TR << "Best fit is conformer " << best_i << " with score " << best_score << std::endl;
143  // Residue library has already superimpose residues appropriately, so don't orient again
144  pose.replace_residue(rsd_no, *(conformers[best_i]), false /*orient backbone*/);
145  }
146 }
147 
148 
150  core::grid::CartGrid<int> const & grid,
151  core::pose::Pose & pose,
152  core::Size rsd_no
153 )
154 {
156 
157  // Retrieve list of conformers
159  rotamers_for_trials(pose, rsd_no, conformers);
160  if( conformers.empty() ) return;
161  TR<< "conformers.size: "<< conformers.size()<< std::endl;
162  // Conformers are already aligned onto original residue coords at this point.
163 
164  // Select best conformer, stopping early if score == 0
165  int const perfect_rep = 0, perfect_atr = -(pose.residue(rsd_no).nheavyatoms());
166  int best_rep = 9999, best_atr = 0;
167  core::Size best_i = 0;
168  for(core::Size i = 1, i_end = conformers.size(); i <= i_end; ++i) {
169  ResidueOP rsd = conformers[i];
170  int new_atr(0), new_rep(0);
171  grid_score_atr_rep(grid, *rsd, new_atr, new_rep, best_rep);
172  if( new_rep < best_rep || (new_rep == best_rep && new_atr < best_atr) ) {
173  best_rep = new_rep;
174  best_atr = new_atr;
175  best_i = i;
176  if(best_rep == perfect_rep && best_atr == perfect_atr) break;
177  }
178  }
179 
180  // Replace current residue with best residue
181  if( best_i > 0 ) {
182  TR << "Best fit is conformer " << best_i << " with score rep=" << best_rep << " atr=" << best_atr << std::endl;
183  // Residue library has already superimpose residues appropriately, so don't orient again
184  pose.replace_residue(rsd_no, *(conformers[best_i]), false /*orient backbone*/);
185  }
186 }
187 
189  core::grid::CartGrid<int> const & grid,
190  core::pose::Pose & pose,
191  core::Size begin,
193 ){
194  // Residues don't interact with each other -- no reason to do this more than
195  // once with the same pose. Likewise, ligand residues don't interact.
196  for(; begin <= end; ++begin){
197  TR<< "now performing rotamer trials on "<< begin << std::endl;
198  grid_rotamer_trials_atr_rep(grid, pose, begin);
199  }
200 }
201 
203  core::pose::Pose & pose,
204  core::Size rsd_no,
206 )
207 {
209  using namespace core::pack::task;
210 
211  // Dummy parameters that the ligand rotamer library doesn't use:
212  core::scoring::ScoreFunction dummy_sfxn;
213  PackerTaskOP dummy_task = TaskFactory::create_packer_task(pose); // actually used, in a trivial way
214 
215  core::graph::GraphCOP empty_graph = new core::graph::Graph();
216  // Retrieve conformers
218  if( reslib.get() == NULL ) return;
219 
220  core::chemical::ResidueType const & res_type = pose.residue_type(rsd_no);
221  utility::vector1< utility::vector1< core::Real > > empty_extra_chi_steps( res_type.nchi(), utility::vector1< core::Real >() );
222 
223  // Retrieve list of conformers
224  reslib->fill_rotamer_vector(
225  pose,
226  dummy_sfxn,
227  *dummy_task,
228  empty_graph,
229  &pose.residue_type(rsd_no), //ResidueTypeCOP
230  pose.residue(rsd_no),
231  empty_extra_chi_steps,
232  true /* sure, let's pretend it's buried */,
233  conformers_out // output appended here
234  );
235  // Conformers are already aligned onto original residue coords at this point.
236 
237  // Because scoring is so "coarse", with many conformers possibly getting the same score,
238  // it's important to try them in random order to avoid biases.
239  numeric::random::random_permutation(conformers_out, my_RG);
240 }
241 
242 
243 /// @details Make a bounding box around the sphere, and visit all grid points
244 /// that the box intersects. If the grid point center is within the sphere,
245 /// fill that grid space with the specified value.
248  core::Vector const & center,
249  core::Real radius,
250  int value
251 )
252 {
253  typedef core::grid::CartGrid<int>::GridPt GridPt;
254  using core::Vector;
255  using namespace std; // min, max
256 
257  core::Real radius2 = radius*radius;
258  int nx(0), ny(0), nz(0); // grid points in each dimension
259  grid.getNumberOfPoints(nx, ny, nz);
260  Vector vec_rad( radius );
261  GridPt grid_min = grid.gridpt( center - vec_rad );
262  GridPt grid_max = grid.gridpt( center + vec_rad );
263  for(int i = max(0, grid_min.x()), i_end = min(nx-1, grid_max.x()); i <= i_end; ++i) {
264  for(int j = max(0, grid_min.y()), j_end = min(ny-1, grid_max.y()); j <= j_end; ++j) {
265  for(int k = max(0, grid_min.z()), k_end = min(nz-1, grid_max.z()); k <= k_end; ++k) {
266  GridPt grid_pt(i, j, k);
267  //std::cout << "Checking grid pt " << i << " " << j << " " << k << std::endl;
268  Vector box_ctr = grid.coords( grid_pt );
269  if( box_ctr.distance_squared(center) <= radius2 ) grid.setValue(grid_pt, value);
270  }
271  }
272  }
273 }
274 
276  // Set repulsive core around each backbone heavy atom (including CB)
277  for(core::Size r = 1, r_end = pose.total_residue(); r <= r_end; ++r) {
278  core::conformation::Residue const & rsd = pose.residue(r);
279  if( !rsd.is_protein() ) continue;
280  if( rsd.has("CB") ) set_sphere(*grid, rsd.xyz("CB"), rep_rad, 1);
281  if( rsd.has("N") ) set_sphere(*grid, rsd.xyz("N"), rep_rad, 1);
282  if( rsd.has("CA") ) set_sphere(*grid, rsd.xyz("CA"), rep_rad, 1);
283  if( rsd.has("C") ) set_sphere(*grid, rsd.xyz("C"), rep_rad, 1);
284  if( rsd.has("O") ) set_sphere(*grid, rsd.xyz("O"), rep_rad, 1);
285  }
286 }
287 
288 /// @detail this function assumes there is only one ligand so it only considers protein residues
290  core::pose::Pose const & pose,
291  core::Vector const & center
292 )
293 {
294  TR << "make_atr_rep_grid"<<std::endl;
295  using namespace core;
296  int const num_pts = 160;
297  Real const resol = 0.25;
298  Real const grid_halfwidth = (num_pts * resol) / 2.0;
299  Real const atr_rad = 4.75; // optimal contact distance <= 4A for most atom pairs (but we're ignoring H)
300  Real const rep_rad = 2.25; // don't want to exclude H-bonds (~2.8A heavy-heavy) or make clefts too narrow
301 
302  // Designer of this class did not believe in RAII:
304  grid->setBase(
305  center.x() - grid_halfwidth,
306  center.y() - grid_halfwidth,
307  center.z() - grid_halfwidth
308  );
309  grid->setDimensions(num_pts, num_pts, num_pts, resol, resol, resol);
310  grid->setupZones();
311  grid->zero();
312 
313  // Set attractive zones around all heavy atoms -- assume most ligand atoms
314  // will be near *something*, and most sidechains will stay put.
315  for(Size r = 1, r_end = pose.total_residue(); r <= r_end; ++r) {
316  conformation::Residue const & rsd = pose.residue(r);
317  if( !rsd.is_protein() ) continue;
318  for(Size a = 1, a_end = rsd.nheavyatoms(); a <= a_end; ++a)
319  {
320  set_sphere(*grid, rsd.xyz(a), atr_rad, -1);
321  }
322  }
323 
324  // Set neutral core around each sidechain heavy atom, as MOST of these stay put.
325  for(Size r = 1, r_end = pose.total_residue(); r <= r_end; ++r) {
326  conformation::Residue const & rsd = pose.residue(r);
327  if( !rsd.is_protein() ) continue;
328  for(Size a = rsd.first_sidechain_atom(), a_end = rsd.nheavyatoms(); a <= a_end; ++a)
329  {
330  set_sphere(*grid, rsd.xyz(a), rep_rad, 0);
331  }
332  }
333 
334  set_repulsive_bb_cores(grid, pose, rep_rad);
335 
336  return grid;
337 }
338 
339 /// @detail this function assumes excludes one ligand from the grid
341  core::pose::Pose const & pose,
342  core::Vector const & center,
343  core::Size const & ligand_chain_id_to_exclude
344 )
345 {
346  utility::vector1<core::Size> ligand_chain_ids_to_exclude;
347  ligand_chain_ids_to_exclude.push_back(ligand_chain_id_to_exclude);
348  return make_atr_rep_grid_without_ligands(pose, center, ligand_chain_ids_to_exclude);
349 }
350 
351 /// @brief Make a grid around the specified point with attractive (negative)
352 /// and repulsive (positive) values for all heavy atoms not in ligand_chain_id_to_exclude
354  core::pose::Pose const & pose,
355  core::Vector const & center,
356  utility::vector1<core::Size> ligand_chain_ids_to_exclude
357 ){
358  TR << "make_atr_rep_grid_without_ligands"<<std::endl;
359  using namespace core;
360  int const num_pts = 160;
361  Real const resol = 0.25;
362  Real const grid_halfwidth = (num_pts * resol) / 2.0;
363  Real const atr_rad = 4.75; // optimal contact distance <= 4A for most atom pairs (but we're ignoring H)
364  Real const rep_rad = 2.25; // don't want to exclude H-bonds (~2.8A heavy-heavy) or make clefts too narrow
365 
366  // Designer of this class did not believe in RAII:
368  grid->setBase(
369  center.x() - grid_halfwidth,
370  center.y() - grid_halfwidth,
371  center.z() - grid_halfwidth
372  );
373  grid->setDimensions(num_pts, num_pts, num_pts, resol, resol, resol);
374  grid->setupZones();
375  grid->zero();
376 
377  // Set attractive zones around all heavy atoms -- assume most ligand atoms
378  // will be near *something*, and most sidechains will stay put.
379  for(Size r = 1, r_end = pose.total_residue(); r <= r_end; ++r) {
380  conformation::Residue const & rsd = pose.residue(r);
381  if( find(
382  ligand_chain_ids_to_exclude.begin(),
383  ligand_chain_ids_to_exclude.end(),
384  rsd.chain()
385  ) != ligand_chain_ids_to_exclude.end()
386  ) {
387  continue;
388  }
389  for(Size a = 1, a_end = rsd.nheavyatoms(); a <= a_end; ++a)
390  {
391  set_sphere(*grid, rsd.xyz(a), atr_rad, -1);
392  }
393  }
394 
395  // Set neutral core around each sidechain heavy atom, as MOST of these stay put.
396  for(Size r = 1, r_end = pose.total_residue(); r <= r_end; ++r) {
397  conformation::Residue const & rsd = pose.residue(r);
398  if( find(
399  ligand_chain_ids_to_exclude.begin(),
400  ligand_chain_ids_to_exclude.end(),
401  rsd.chain()
402  ) != ligand_chain_ids_to_exclude.end()
403  ) {
404  continue;
405  }
406  if( rsd.is_protein() ){
407  for(Size a = rsd.first_sidechain_atom(), a_end = rsd.nheavyatoms(); a <= a_end; ++a)
408  {
409  set_sphere(*grid, rsd.xyz(a), rep_rad, 0);//ligand can run into side-chains, they'll be repacked
410  }
411  }else{
412  for(Size a = 1, a_end = rsd.nheavyatoms(); a <= a_end; ++a)
413  {
414  set_sphere(*grid, rsd.xyz(a), rep_rad, 1); //ligand shouldn't run into other ligands
415  }
416  }
417  // else don't add this ligand to the grid
418  }
419 
420  set_repulsive_bb_cores(grid, pose,rep_rad);
421 
422  return grid;
423 }
424 
425 
426 
427 
428 
429 } // namespace ligand_docking
430 } // namespace protocols