Rosetta 3.5
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
LigandConformer.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/LigandConformer.cc
12 /// @brief Implementation for class to hold a ligand conformation
13 /// @author Alex Zanghellini (zanghell@u.washington.edu)
14 /// @author Andrew Leaver-Fay (aleaverfay@gmail.com), porting to mini
15 
16 /// Unit headers
18 
19 // Project headers
23 
24 // ObjexxFCL headers
25 #include <ObjexxFCL/FArray2D.hh>
26 
27 // Utility headers
28 #include <utility/vector1.functions.hh>
29 
30 #include <core/id/AtomID.hh>
31 #include <utility/vector1.hh>
32 
33 
34 namespace protocols {
35 namespace toolbox {
36 namespace match_enzdes_util {
37 
38 
40  parent(),
41  d12_( 1.0 ),
42  d23_( 1.0 ),
43  ang123_( 109.5 ),
44  ignore_h_collisions_( false )
45 {}
46 
48  parent( other ),
49  ligand_restype_( other.ligand_restype_ ),
50  orientation_atoms_( other.orientation_atoms_ ),
51  oats_in_D3_frame_( other.oats_in_D3_frame_ ),
52  oframe_in_D3frame_( other.oframe_in_D3frame_ ),
53  points_in_global_orintation_frame_( other.points_in_global_orintation_frame_ ),
54  atoms_123_( other.atoms_123_ ),
55  d12_( other.d12_ ),
56  d23_( other.d23_ ),
57  ang123_( other.ang123_ ),
58  points_in_D3_frame_( other.points_in_D3_frame_ ),
59  collision_check_id_2_restype_id_( other.collision_check_id_2_restype_id_ ),
60  restype_id_2_collision_check_id_( other.restype_id_2_collision_check_id_ )
61 {}
62 
64 
67 {
68  assert( ligand_restype_ );
69  return d12_;
70 }
71 
72 
75 {
76  assert( ligand_restype_ );
77  return d23_;
78 }
79 
80 /// @brief Returns an angle in degrees between the three downstream atoms.
81 
84 {
85  assert( ligand_restype_ );
86  return ang123_;
87 }
88 
89 
92 {
93  assert( ligand_restype_ );
94  return points_in_D3_frame_[ orientation_atoms_[ 1 ] ].distance(
96 }
97 
100 {
101  assert( ligand_restype_ );
102  return points_in_D3_frame_[ orientation_atoms_[ 2 ] ].distance(
104 }
105 
108 {
109  assert( ligand_restype_ );
110  return numeric::constants::d::radians_to_degrees *
111  numeric::angle_radians(
113  points_in_D3_frame_[ orientation_atoms_[ 2 ] ],
114  points_in_D3_frame_[ orientation_atoms_[ 3 ] ] );
115 }
116 
117 
118 void
120  Real6 const & orientation,
121  utility::vector1< core::id::AtomID > const & atom_indices,
122  utility::vector1< Vector > & atom_coords
123 ) const
124 {
125  //for ( Size jj=1; jj != points_in_global_orintation_frame_.size(); ++jj ) {
126  // std::cout << "atomno " << jj << " " << points_in_global_orintation_frame_[jj][0] << " " << points_in_global_orintation_frame_[jj][1] << " " << points_in_global_orintation_frame_[jj][2] << std::endl;
127  //}
128 
129  //std::cout << "LigandConformer::coordinates from hit begin" << std::endl;
130  //std::cout << "hit: " << hit.first()[1] << " "<< hit.first()[2] << " "<< hit.first()[3] << " "<< hit.first()[4] << " " << std::endl;
131  //std::cout << "hit: " << hit.second()[1] << " "<< hit.second()[2] << " "<< hit.second()[3] << " "<< hit.second()[4] << " " << hit.second()[5] << " "<< hit.second()[6] << " " << std::endl;
132  //std::cout << "atom_indices.size() " << atom_indices.size() << std::endl;
133  //std::cout << "points_in_global_orintation_frame_.size() " << points_in_global_orintation_frame_.size() << std::endl;
134 
135  HTReal global_frame = frame_from_global_orientation( orientation );
136  for ( Size ii = 1; ii <= atom_indices.size(); ++ii ) {
137  //std::cout << "atom_indices[ ii ].atomno() " << ii << " " << atom_indices[ ii ].atomno() << std::endl;
138  assert( atom_indices[ ii ].rsd() == 1 );
139  atom_coords[ ii ] = global_frame * points_in_global_orintation_frame_[ atom_indices[ ii ].atomno() ];
140  //std::cout << "x: " << atom_coords[ ii ][0] << " y: " << atom_coords[ ii ][1] << " z: "<< atom_coords[ ii ][2] << std::endl;
141  }
142 
143  //std::cout << "LigandConformer::coordinates from hit begin" << std::endl;
144 }
145 
146 void
148  Size D1,
149  Size D2,
150  Size D3,
151  Size orientation_atom1,
152  Size orientation_atom2,
153  Size orientation_atom3,
154  core::conformation::Residue const & residue
155 )
156 {
157  //std::cout << "APL DEBUG LigandConformer::initialize_from_residue begin " << std::endl;
158 
159  atoms_123_[ 1 ] = D1;
160  atoms_123_[ 2 ] = D2;
161  atoms_123_[ 3 ] = D3;
162 
163  /// Measure the two distances and one angle needed to describe the geometry of this ligand
164  /// to the ClassicMatchAlgorithm.
165  d12_ = residue.xyz( D1 ).distance( residue.xyz( D2 ) );
166  d23_ = residue.xyz( D2 ).distance( residue.xyz( D3 ) );
167  ang123_ = numeric::constants::d::radians_to_degrees * numeric::angle_radians(
168  residue.xyz( D1 ), residue.xyz( D2 ), residue.xyz( D3 ) );
169 
170  orientation_atoms_[ 1 ] = orientation_atom1;
171  orientation_atoms_[ 2 ] = orientation_atom2;
172  orientation_atoms_[ 3 ] = orientation_atom3;
173 
174  Size const natoms = residue.natoms();
175  if ( natoms < 3 ) {
176  utility_exit_with_message( "ERROR in LigandConformer: cannot build a residue with fewer than three atoms" );
177  }
178 
179  ligand_restype_ = & residue.type();
180  HTReal D3frame( residue.xyz( D1 ), residue.xyz( D2 ), residue.xyz( D3 ) );
181  HTReal oframe( residue.xyz( orientation_atom1 ), residue.xyz( orientation_atom2 ), residue.xyz( orientation_atom3 ) );
182 
183  oframe_in_D3frame_ = D3frame.inverse() * oframe;
184 
185  //std::cout << "APL DEBUG LigandConformer::initialize_from_residue natoms " << natoms << std::endl;
186  points_in_global_orintation_frame_.resize( natoms );
187  points_in_D3_frame_.resize( natoms );
188  for ( Size ii = 1; ii <= natoms; ++ii ) {
189  points_in_global_orintation_frame_[ ii ] = oframe.to_local_coordinate( residue.xyz( ii ) );
190  points_in_D3_frame_[ ii ] = D3frame.to_local_coordinate( residue.xyz( ii ) );
191  }
192 
193  bool const atom1_virtual = residue.atom_type( D1 ).name() == "X";
194  bool const atom2_virtual = residue.atom_type( D2 ).name() == "X";
195  bool const atom3_virtual = residue.atom_type( D3 ).name() == "X";
196 
197  bool atom1_heavy = residue.atom_type( D1 ).element() != "H" && ! atom1_virtual;
198  bool atom2_heavy = residue.atom_type( D2 ).element() != "H" && ! atom2_virtual;
199  bool atom3_heavy = residue.atom_type( D3 ).element() != "H" && ! atom3_virtual;
200 
201  Size nvirt( 0 );
202  for ( Size ii = 1; ii <= natoms; ++ii ) if ( residue.atom_type( ii ).element() == "X" ) ++nvirt;
203 
204  Size const n_atoms_for_collision_check( ignore_h_collisions_ ?
205  residue.nheavyatoms() - ( atom1_heavy ? 1 : 0 ) - ( atom2_heavy ? 1 : 0 ) - ( atom3_heavy ? 1 : 0 ) :
206  natoms - nvirt - ( atom1_virtual ? 0 : 1 ) - ( atom2_virtual ? 0 : 1 ) - ( atom3_virtual ? 0 : 1 ));
207 
208  collision_check_id_2_restype_id_.resize( n_atoms_for_collision_check );
209  restype_id_2_collision_check_id_.resize( natoms, 0 );
210 
211  utility::vector1< bool > selected( natoms, false );
212  selected[ D1 ] = selected[ D2 ] = selected[ D3 ] = true;
213  create_collcheck_ordering( selected, 1 );
214 
215  oats_in_D3_frame_[ 1 ] = D3frame.to_local_coordinate( residue.xyz( orientation_atoms_[ 1 ] ));
216  oats_in_D3_frame_[ 2 ] = D3frame.to_local_coordinate( residue.xyz( orientation_atoms_[ 2 ] ));
217  oats_in_D3_frame_[ 3 ] = D3frame.to_local_coordinate( residue.xyz( orientation_atoms_[ 3 ] ));
218 
219  //std::cout << "APL DEBUG LigandConformer::initialize_from_residue end " << std::endl;
220 
221 }
222 
223 
226  HTReal const & frame3
227 ) const
228 {
229  HTReal global_frame = frame3 * oframe_in_D3frame_;
230  //std::cout.precision( 12 );
231  //std::cout << "Global frame" << std::endl;
232  //std::cout << " " << global_frame.xx() << " " << global_frame.yx() << " " << global_frame.zx() << " " << global_frame.px() << std::endl;
233  //std::cout << " " << global_frame.xy() << " " << global_frame.yy() << " " << global_frame.zy() << " " << global_frame.py() << std::endl;
234  //std::cout << " " << global_frame.xz() << " " << global_frame.yz() << " " << global_frame.zz() << " " << global_frame.pz() << std::endl;
235  //std::cout.precision( 6 );
236 
237  Vector euler_angles = global_frame.euler_angles_deg();
238  for ( Size ii = 1; ii <= 3; ++ii ) if ( euler_angles( ii ) < 0 ) euler_angles( ii ) += 360.0;
239  Vector oat3_coords = global_frame.point(); //frame3 * points_in_at3_frame_[ restype_id_2_at3_frame_id_[ orientation_atoms_[ 3 ]]];
240 
241  Real6 global_coords;
242  global_coords[ 1 ] = oat3_coords( 1 );
243  global_coords[ 2 ] = oat3_coords( 2 );
244  global_coords[ 3 ] = oat3_coords( 3 );
245  global_coords[ 4 ] = euler_angles( 1 );
246  global_coords[ 5 ] = euler_angles( 2 );
247  global_coords[ 6 ] = euler_angles( 3 );
248 
249 
250 
251  /*if ( false ) {
252 
253  Vector oat1_coord = frame3 * oats_in_at3_frame_[ 1 ];
254  Vector oat2_coord = frame3 * oats_in_at3_frame_[ 2 ];
255  Vector oat3_coord = frame3 * oats_in_at3_frame_[ 3 ];
256  HTReal global_frame2( oat1_coord, oat2_coord, oat3_coord );
257  Vector euler_angles2 = global_frame2.euler_angles_deg();
258  std::cout << "Euler angle comparison.";
259  std::cout << " 1: " << euler_angles( 1 ) << " vs " << euler_angles2( 1 ) << " ";
260  std::cout << " 2: " << euler_angles( 2 ) << " vs " << euler_angles2( 2 ) << " ";
261  std::cout << " 3: " << euler_angles( 3 ) << " vs " << euler_angles2( 3 ) << std::endl;
262 
263  for ( Size ii = 1; ii <= points_in_D3_frame_.size(); ++ii ) {
264  Vector ii3loc = frame3 * points_in_D3_frame_[ ii ];
265  Vector iigloc = global_frame * points_in_global_orintation_frame_[ at3_frame_id_2_restype_id_[ ii ]];
266  for ( Size jj = 1; jj <= 3; ++jj ) {
267  std::cout << ii << " " << jj << " " << ii3loc( jj ) << " " << iigloc( jj ) << std::endl;
268  }
269  }
270 
271  HTReal global_frame3;
272  global_frame3.from_euler_angles_deg( euler_angles );
273  global_frame3.set_point( oat3_coord );
274  //std::cout.precision( 12 );
275  std::cout << "Global frame3" << std::endl;
276  std::cout << " " << global_frame3.xx() << " " << global_frame3.yx() << " " << global_frame3.zx() << " " << global_frame3.px() << std::endl;
277  std::cout << " " << global_frame3.xy() << " " << global_frame3.yy() << " " << global_frame3.zy() << " " << global_frame3.py() << std::endl;
278  std::cout << " " << global_frame3.xz() << " " << global_frame3.yz() << " " << global_frame3.zz() << " " << global_frame3.pz() << std::endl;
279  //std::cout.precision( 6 );
280  }*/
281 
282  return global_coords;
283 }
284 
287  Real6 orientation
288 ) const
289 {
290  Vector oat3_coord(orientation[ 1 ], orientation[ 2 ], orientation[ 3 ] );
291  Vector euler_deg( orientation[ 4 ], orientation[ 5 ], orientation[ 6 ] );
292 
293  //std::cout << "oat3_coord: " << oat3_coord(1) << " " << oat3_coord(2) << " " << oat3_coord(3) << std::endl;
294  //std::cout << "euler_deg: " << euler_deg(1) << " " << euler_deg(2) << " " << euler_deg(3) << std::endl;
295 
296  HTReal oframe;
297 
298  oframe.from_euler_angles_deg( euler_deg );
299  oframe.set_point( oat3_coord );
300 
301  //std::cout.precision( 12 );
302  //std::cout << "Global frame" << std::endl;
303  //std::cout << " " << oframe.xx() << " " << oframe.yx() << " " << oframe.zx() << " " << oframe.px() << std::endl;
304  //std::cout << " " << oframe.xy() << " " << oframe.yy() << " " << oframe.zy() << " " << oframe.py() << std::endl;
305  //std::cout << " " << oframe.xz() << " " << oframe.yz() << " " << oframe.zz() << " " << oframe.pz() << std::endl;
306  //std::cout.precision( 6 );
307 
308  Vector euler_deg2 = oframe.euler_angles_deg();
309  //std::cout << "reverse euler angles: " << euler_deg2(1) << " " << euler_deg2(2) << " " << euler_deg2(3) << std::endl;
310 
311  return oframe;
312 }
313 
314 void
316 {
317  if ( ligand_restype_ != 0 ) {
318  utility_exit_with_message( "ERROR: ignore_h_collisions_ must be set before the downstream restype is initialized" );
319  } else {
320  ignore_h_collisions_ = setting;
321  }
322 }
323 
324 void
326  utility::vector1< Size > const & restype_atnos_to_move_early
327 )
328 {
329  Size start_from( 1 );
331  for ( Size ii = 1; ii <= restype_atnos_to_move_early.size(); ++ii ) {
332  Size iiatom = restype_atnos_to_move_early[ ii ];
333  if ( restype_id_2_collision_check_id_[ iiatom ] == 0 ) continue;
334  selected[ iiatom ] = true;
335  ++start_from;
336 
337  collision_check_id_2_restype_id_[ ii ] = iiatom;
338  restype_id_2_collision_check_id_[ iiatom ] = ii;
339 
340  }
341  for ( Size ii = 1; ii <= 3; ++ii ) {
342  if ( selected[ atoms_123_[ ii ]] ) {
343  --start_from;
344  } else {
345  selected[ atoms_123_[ ii ]] = true;
346  }
347  }
348  create_collcheck_ordering( selected, start_from );
349 }
350 
351 
352 void
354  ObjexxFCL::FArray2D< numeric::Real > & coords,
355  HTReal const & orientation_frame,
356  utility::vector1< core::Size > const & restype_atomnos
357 ) const
358 {
359  for( core::Size ii = 1; ii <= restype_atomnos.size(); ++ii ){
360  Vector coord( orientation_frame * points_in_global_orintation_frame_[ restype_atomnos[ ii ] ] );
361  coords( 1, ii ) = coord[0];
362  coords( 2, ii ) = coord[1];
363  coords( 3, ii ) = coord[2];
364  }
365 }
366 
367 
368 void
370  utility::vector1< bool > selected,
371  Size count_from
372 )
373 {
374  Size const natoms = ligand_restype_->natoms();
375  Size const n_atoms_for_collision_check = collision_check_id_2_restype_id_.size();
376 
377  /// Order the other atoms by their distance from D3 and the atoms already selected.
378  ObjexxFCL::FArray2D< Real > atdists( natoms, natoms );
379  utility::vector1< Real > atdist_sums( natoms, 0.0 );
380  utility::vector1< bool > ignore( natoms, false );
381  for ( Size ii = 1; ii <= natoms; ++ii ) {
382  if ( ignore_h_collisions_ && ligand_restype_->atom_type( ii ).element() == "H" ) ignore[ ii ] = true;
383  if ( ligand_restype_->atom_type( ii ).element() == "X" ) ignore[ ii ] = true;
384  if ( ignore[ ii ] ) continue;
385 
386  for( Size jj = ii + 1; jj <= natoms; ++jj ) {
387  atdists( ii, jj ) = atdists( jj, ii ) = points_in_D3_frame_[ ii ].distance( points_in_D3_frame_[ jj ] );
388  }
389  }
390 
391  /// O( N^3 )... but a one-time cost and way fast. The question is, though,
392  /// whether this shuffling of atoms yeilds a speedup and if so, how much?
393  for ( Size ii = count_from; ii <= n_atoms_for_collision_check; ++ii ) {
394  /// set the atdist sums to zero.
395  std::fill( atdist_sums.begin(), atdist_sums.end(), 0.0);
396  for ( Size jj = 1; jj <= natoms; ++jj ) {
397  if ( selected[ jj ] || ignore[ jj ] ) {
398  atdist_sums[ jj ] = -1.0; // make sure this atom is not the furthest atom.
399  } else {
400  for ( Size kk = 1; kk <= natoms; ++kk ) {
401  if ( ignore[ kk ] ) continue;
402  if ( selected[ kk ] ) atdist_sums[ jj ] += atdists( kk, jj );
403  }
404  }
405  //std::cout << ii << " " << jj << " " << atdist_sums[ jj ] << std::endl;
406  }
407 
408  Size furthest = utility::arg_max( atdist_sums );
409  //std::cout << ii << " furthest: " << furthest << " " << ligand_restype_->atom_name( furthest ) << std::endl;
410  collision_check_id_2_restype_id_[ ii ] = furthest;
411  restype_id_2_collision_check_id_[ furthest ] = ii;
412  selected[ furthest ] = true;
413  }
414 
415 }
416 
419  return * ligand_restype_;
420 }
421 
422 
423 
424 }
425 }
426 }