Rosetta 3.5
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
LigandConformerBuilder.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/match/downstream/LigandConformerBuilder.cc
12 /// @brief
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 /// Package headers
23 
24 // Project headers
28 
29 // AUTO-REMOVED #include <core/conformation/util.hh>
30 
31 #include <core/pose/Pose.hh>
32 #include <core/pose/PDBInfo.hh>
33 
34 // AUTO-REMOVED #include <core/scoring/ScoringManager.hh>
37 
39 
40 #include <basic/Tracer.hh>
41 
42 // ObjexxFCL headers
43 #include <ObjexxFCL/FArray2D.hh>
44 
45 // Utility headers
46 // AUTO-REMOVED #include <utility/vector1.functions.hh>
47 #include <utility/exit.hh>
48 #include <utility/string_util.hh>
49 
50 //numeric headers
51 #include <numeric/model_quality/rms.hh>
52 
53 #include <core/id/AtomID.hh>
54 #include <protocols/match/Hit.hh>
55 #include <utility/vector1.hh>
56 
57 
58 namespace protocols {
59 namespace match {
60 namespace downstream {
61 
62 static basic::Tracer TR( "protocols.match.downstream.LigandConformerBuilder" );
63 
65  parent(),
66  ignore_h_collisions_( false ),
67  idealize_conformers_( true ),
68  rmsd_unique_cutoff_(0.05)
69 {
70  //std::cout << "APL DEBUG LigandConformerBuilder ctor " << this << std::endl;
71 }
72 
74  parent( other ),
75  downstream_restype_( other.downstream_restype_ ),
76  upstream_restype_( other.upstream_restype_ ),
77  ignore_h_collisions_( other.ignore_h_collisions_ ),
78  idealize_conformers_( other.idealize_conformers_ ),
79  orientation_atoms_( other.orientation_atoms_ ),
80  atoms_123_( other.atoms_123_ ),
81  radii_123_( other.radii_123_ ),
82  ats123_reqd_in_active_site_( other.ats123_reqd_in_active_site_ ),
83  atom_radii_( other.atom_radii_ ),
84  atom_required_in_active_site_( other.atom_required_in_active_site_ ),
85  non_collision_detection_atoms_reqd_in_active_site_( other.non_collision_detection_atoms_reqd_in_active_site_ ),
86  rmsd_unique_cutoff_( other.rmsd_unique_cutoff_ ),
87  conformer_group_indices_( other.conformer_group_indices_ ),
88  lig_conformers_( other.lig_conformers_.size() ),
89  min_sep_d2_from_upstream_atoms_( other.min_sep_d2_from_upstream_atoms_ )
90 {
91  for ( Size ii = 1; ii <= lig_conformers_.size(); ++ii ) {
93  }
94  //std::cout << "APL DEBUG LigandConformerBuilder copy ctor " << this << std::endl;
95 }
96 
97 //LigandConformerBuilder::LigandConformerBuilder( LigandConformerBuilder const & other, core::chemical::ResidueTypeCOP upstream_restype ) :
98 // parent(other),
99 // downstream_restype_( other.downstream_restype_ ),
100 // upstream_restype_( upstream_restype ),
101 // ignore_h_collisions_( other.ignore_h_collisions_ ),
102 // atom_radii_( other.atom_radii_ ),
103 // atom_required_in_active_site_( other.atom_required_in_active_site_ ),
104 // non_collision_detection_atoms_reqd_in_active_site_( other.non_collision_detection_atoms_reqd_in_active_site_ ),
105 // lig_conformers_( other.lig_conformers_.size() )
106 //{
107 // for ( Size ii = 1; ii <= lig_conformers_.size(); ++ii ) {
108 // lig_conformers_[ ii ] = new LigandConformer( * other.lig_conformers_[ ii ] );
109 // //TR << "Nr of n_collision_check_atoms: " << lig_conformers_[ ii ]->n_collision_check_atoms() << std::endl;
110 // runtime_assert(lig_conformers_[ ii ]);
111 // }
112 //
113 // initialize_upstream_residue( upstream_restype );
114 //}
115 
116 
118 
121 {
122  return new LigandConformerBuilder( *this );
123 }
124 
125 
126 std::list< Hit >
128  HTReal const & atom3_frame,
129  Size const scaffold_build_point_id,
130  Size const upstream_conf_id,
131  Size const external_geometry_id,
132  core::conformation::Residue const & upstream_residue
133 ) const
134 {
135  std::list< Hit > hitlist;
136  for ( Size ii = 1; ii <= conformer_group_indices_.size(); ++ii ) {
137  std::list< Hit > ii_hits = build_conformer_group( ii, atom3_frame, scaffold_build_point_id,
138  upstream_conf_id, external_geometry_id, upstream_residue );
139  hitlist.splice( hitlist.end(), ii_hits );
140  }
141  return hitlist;
142 }
143 
144 void
146  utility::vector1< core::Size > const & relevant_atom_indices
147 )
148 {
149  Size num_relevant_atoms( relevant_atom_indices.size() );
150  conformer_group_indices_.clear();
152  conformer_group_indices_[1].push_back( 1 ); //first one is always unique
154  conformer_group_for_conformer_.push_back( 1 ); //the conformer group for the first conformer is always 1
155  HTReal identity_ht;
156 
157  for( Size ii = 2; ii <= lig_conformers_.size(); ++ii ){
158 
159  ObjexxFCL::FArray2D< numeric::Real > queryconf_coord( 3, num_relevant_atoms );
160  lig_conformers_[ii]->get_global_coords_as_FArray2D( queryconf_coord, identity_ht, relevant_atom_indices );
161 
162  bool conformer_unique(true);
163  for( Size jj = 1; jj <= conformer_group_indices_.size(); ++jj){
164 
165  ObjexxFCL::FArray2D< numeric::Real > uniqueconf_coord( 3, num_relevant_atoms );
166  lig_conformers_[ conformer_group_indices_[jj][1] ]->get_global_coords_as_FArray2D( uniqueconf_coord, identity_ht, relevant_atom_indices );
167 
168  Real rmsd_this_pair = numeric::model_quality::rms_wrapper( num_relevant_atoms, queryconf_coord, uniqueconf_coord );
169  if( rmsd_this_pair < rmsd_unique_cutoff_ ){
170  conformer_group_indices_[jj].push_back( ii );
171  conformer_group_for_conformer_.push_back( jj );
172  //std::cerr << "lig conf " << ii << " identical to conf " << conformer_group_indices_[jj][1] << std::endl;
173  conformer_unique = false;
174  break;
175  }
176  } //loop over conformer groups
177 
178  if( conformer_unique ){
180  conformer_group_indices_[ conformer_group_indices_.size() ].push_back( ii );
182  //std::cerr << "lig conf " << ii << "detected to be unique" << std::endl;
183  }
184  } //loop over all lig_conformers 2->n
185  TR << "Ligand conformers were split up into " << conformer_group_indices_.size() << " match-redundant groups." << std::endl;
186 }
187 
188 void
190  BumpGridCOP bbgrid
191 )
192 {
193  parent::set_bb_grid( bbgrid );
194  if ( upstream_restype_ ) {
196  }
197 }
198 
199 bool
201 {
202  if( conformer_group_indices_.size() > 1 ) return true;
203  return false;
204 }
205 
206 bool
208  Hit const & my_hit,
209  DownstreamBuilder const & other,
210  Hit const & other_hit,
211  bool //first_dispatch
212 ) const
213 {
214  return other.compatible( other_hit, *this, my_hit, false );
215 }
216 
217 /// @details LigandConformerBuilder checks whether the ligand conformers
218 /// in both hits are in the same conformer group
219 bool
221  Hit const & my_hit,
222  LigandConformerBuilder const & other,
223  Hit const & other_hit,
224  bool //first_dispatch
225 ) const
226 {
227  if( conformer_group_for_conformer_[ my_hit.downstream_conf_id() ] == other.conformer_group_for_conformer_[ other_hit.downstream_conf_id() ] ) return true;
228  return false;
229 }
230 
231 
232 void
234  core::id::AtomID const & id
235 )
236 {
237  runtime_assert( id.rsd() == 1 );
238  runtime_assert( id.atomno() < downstream_restype_->natoms() );
239  if ( lig_conformers_[ 1 ]->restype_id_2_collision_check_id( id.atomno() ) == 0 ) {
241  } else {
242  atom_required_in_active_site_[ id.atomno() ] = true;
243  for ( Size ii = 1; ii <= 3; ++ii ) {
244  if ( atoms_123_[ ii ] == id.atomno() ) {
245  ats123_reqd_in_active_site_[ ii ] = true;
246  break;
247  }
248  }
249  }
250 }
251 
254 {
255  assert( downstream_restype_ );
256  //return ZERO;
257  return radii_123_[ 1 ];
258 }
259 
260 
263 {
264  assert( downstream_restype_ );
265  return radii_123_[ 2 ];
266 }
267 
268 
271 {
272  assert( downstream_restype_ );
273  return radii_123_[ 3 ];
274 }
275 
276 
277 bool
279 {
280  return ats123_reqd_in_active_site_[ 1 ];
281 }
282 
283 bool
285 {
286  return ats123_reqd_in_active_site_[ 2 ];
287 }
288 
289 bool
291 {
292  return ats123_reqd_in_active_site_[ 3 ];
293 }
294 
297 {
298  assert( downstream_restype_ );
299  return lig_conformers_[ 1 ]->atom1_atom2_distance();
300 }
301 
302 
305 {
306  assert( downstream_restype_ );
307  return lig_conformers_[ 1 ]->atom2_atom3_distance();
308 }
309 
310 /// @brief Returns an angle in degrees between the three downstream atoms.
311 
314 {
315  assert( downstream_restype_ );
316  return lig_conformers_[ 1 ]->atom1_atom2_atom3_angle();
317 }
318 
319 
320 void
322  Hit const & hit,
323  utility::vector1< AtomID > const & atom_indices,
324  utility::vector1< Vector > & atom_coords
325 ) const
326 {
327  //std::cout << "APL DEBUG coordinates_from_hit LigandConformerBuilder" << this << std::endl;
328 
329  lig_conformers_[ hit.downstream_conf_id() ]->coordinates_from_orientation( hit.second(), atom_indices, atom_coords );
330 }
331 
332 
333 
336  Hit const & hit
337 ) const
338 {
339 
341 
342  HTReal global_frame = lig_conformers_[ hit.downstream_conf_id() ]->frame_from_global_orientation( hit.second() );
343  for ( Size ii = 1; ii <= lig_res.natoms(); ++ii ) {
344  lig_res.set_xyz( ii, lig_conformers_[ hit.downstream_conf_id() ]->
345  coordinate_in_global_frame( ii, global_frame ) );
346  }
347 
349  pose->append_residue_by_jump( lig_res, 1 );
350 
351  //we should also set a different chain for the downstream pose
352  core::pose::PDBInfoOP pdbinf = new core::pose::PDBInfo( *pose );
353  pose->pdb_info( pdbinf );
354  pose->pdb_info()->chain( 1, 'X' );
355 
356  return pose;
357 
358 }
359 
362 {
363  return lig_conformers_.size();
364 }
365 
366 
367 
368 void
370  Size atom1,
371  Size atom2,
372  Size atom3,
373  Size orientation_atom1,
374  Size orientation_atom2,
375  Size orientation_atom3,
376  core::conformation::Residue const & residue
377 )
378 {
379  TR << "Initializing from residue " << residue.name() << std::endl;
380 
381  atoms_123_[ 1 ] = atom1;
382  atoms_123_[ 2 ] = atom2;
383  atoms_123_[ 3 ] = atom3;
384 
385  orientation_atoms_[ 1 ] = orientation_atom1;
386  orientation_atoms_[ 2 ] = orientation_atom2;
387  orientation_atoms_[ 3 ] = orientation_atom3;
388 
389  Size const natoms = residue.natoms();
390  if ( natoms < 3 ) {
391  utility_exit_with_message( "ERROR in LigandConformerBuilder: cannot build a residue with fewer than three atoms" );
392  }
393  downstream_restype_ = & residue.type();
394  atom_radii_.resize( natoms );
395  atom_required_in_active_site_.resize( natoms, false );
396 
397  for ( Size ii = 1; ii <= natoms; ++ii ) {
398  atom_radii_[ ii ] = probe_radius_for_atom_type( residue.atom( ii ).type() );
399  }
400 
401  initialize_conformers( residue );
402 
403  for ( Size ii = 1; ii <= 3; ++ii ) {
404  if ( ignore_h_collisions_ && residue.atom_type( atoms_123_[ ii ] ).element() == "H" ) {
405  radii_123_[ ii ] = ZERO;
406  } else {
407  radii_123_[ ii ] = probe_radius_for_atom_type( residue.atom( atoms_123_[ ii ] ).type() );
408  }
409  }
410 }
411 
412 
413 void
415  core::chemical::ResidueTypeCOP upstream_res,
417 )
418 {
419  assert( downstream_restype_ );
420  assert( upstream_res );
421 
422  upstream_restype_ = upstream_res;
423 
424  Size const natoms = downstream_restype_->natoms();
425 
427  min_sep_d2_from_upstream_atoms_.resize( natoms );
428 
429  for ( Size ii = 1; ii <= lig_conformers_[ 1 ]->n_collision_check_atoms(); ++ii ) {
430  Size ii_restype_id = lig_conformers_[ 1 ]->collision_check_id_2_restype_id( ii );
431 
432  Size n_to_count( 0 );
433  for ( Size jj = upstream_restype_->first_sidechain_atom();
434  jj <= upstream_restype_->nheavyatoms(); ++jj ) {
435  Real weight( 1.0 );
436  Size path_dist( 0 );
437  if ( ! count_pair || ( count_pair->count( jj, ii_restype_id, weight, path_dist ) && weight == 1.0 ) ) {
438  ++n_to_count;
439  //std::cout << "Bump check " << downstream_restype_->atom_name( ii_restype_id );
440  //std::cout << " on " << downstream_restype_->name() << " with ";
441  //std::cout << upstream_restype_->atom_name( jj ) << " on " << upstream_restype_->name() << std::endl;
442  }
443  }
444  /// Now make sure that if we're within count-pair striking distance of the backbone so that we don't
445  /// reject a conformation due to this atom as registering a collision in bump_grid.occupied()
446  for ( Size jj = 1; jj < upstream_restype_->first_sidechain_atom(); ++jj ) {
447  if ( jj > upstream_restype_->natoms() ) break;
448  Real weight( 1.0 );
449  Size path_dist( 0 );
450  if ( count_pair && ( ! count_pair->count( jj, ii_restype_id, weight, path_dist ) || weight != 1.0 )) {
451  /// WITHIN STRIKING DISTANCE OF BACKBONE! DO NOT COLLISON-CHECK THIS ATOM
452  atom_radii_[ ii_restype_id ] = ZERO;
453  }
454  }
455  min_sep_d2_from_upstream_atoms_[ ii_restype_id ].resize( n_to_count );
456  n_to_count = 0;
457  for ( Size jj = upstream_restype_->first_sidechain_atom();
458  jj <= upstream_restype_->nheavyatoms(); ++jj ) {
459  Real weight( 1.0 );
460  Size path_dist( 0 );
461  if ( ! count_pair || ( count_pair->count( jj, ii_restype_id, weight, path_dist ) && weight == 1.0 ) ) {
462  min_sep_d2_from_upstream_atoms_[ ii_restype_id ][ ++n_to_count ].first = jj;
463  }
464  }
465  }
466 
467  /// Now check atoms D1, D2, and D3 and makes sure they are not within striking distance of the backbone
468  /// If they are, then set their radii to ZERO
469  for ( Size ii = 1; ii <= 3; ++ii ) {
470  if ( count_pair ) {
471  Size ii_id = atoms_123_[ ii ];
472  for ( Size jj = 1; jj < upstream_restype_->first_sidechain_atom(); ++jj ) {
473  Real weight( 1.0 );
474  Size path_dist( 0 );
475  if ( ! count_pair->count( jj, ii_id, weight, path_dist ) || weight != 1.0 ) {
476  radii_123_[ ii ] = ZERO;
477  break;
478  }
479  }
480  }
481  }
482 
483  if ( bbgrid_set() ) {
485  }
486 
487 }
488 
489 void
491 {
492  if ( downstream_restype_ != 0 ) {
493  utility_exit_with_message( "ERROR: ignore_h_collisions_ must be set before the downstream restype is initialized" );
494  } else {
495  ignore_h_collisions_ = setting;
496  }
497 }
498 
499 std::list< Hit >
501  Size const confgrp_id,
502  HTReal const & atom3_frame,
503  Size const scaffold_build_point_id,
504  Size const upstream_conf_id,
505  Size const external_geometry_id,
506  core::conformation::Residue const & upstream_residue
507 ) const
508 {
509  assert( downstream_restype_ );
510  assert( upstream_restype_ );
511  assert( bbgrid_set() );
512  assert( (& upstream_residue.type()) == upstream_restype_.get() );
513 
514  std::list< Hit > hitlist;
515 
516  for ( Size ii = 1; ii <= conformer_group_indices_[ confgrp_id ].size(); ++ii ) {
517  Size ii_conf_id = conformer_group_indices_[ confgrp_id ][ ii ];
518  //std::cout << "LigandConformerBuilder::build" << std::endl;
519  //for ( Size jj = 1; jj <= 3; ++jj ) {
520  //Vector const jjloc = atom3_frame * ats123_in_atom3_frame_[ jj ];
521  //std::cout << "Atom D" << jj << " coordinate: " << jjloc.x() << " " << jjloc.y() << " " << jjloc.z() << std::endl;
522  //}
523 
524  /// collision detection and active-site containment enforcement.
525  bool ii_good( true );
526  for ( Size jj = 1; jj <= lig_conformers_[ ii_conf_id ]->n_collision_check_atoms(); ++jj ) {
527  Size jj_restype_id = lig_conformers_[ ii_conf_id ]->collision_check_id_2_restype_id( jj );
528 
529  Vector const jjloc = lig_conformers_[ ii_conf_id ]->coordinate_in_D3_frame( jj_restype_id, atom3_frame );
530  //std::cout << " " << downstream_restype_->atom_name( at3_frame_id_2_restype_id_[ jj ] ) << " ";
531  //std::cout << jjloc.x() << " " << jjloc.y() << " " << jjloc.z() << std::endl;
532  if ( atom_radii_[ jj_restype_id ] > ZERO && bbgrid().occupied( atom_radii_[ jj_restype_id ], jjloc ) ) {
533  ii_good = false;
534  break;
535  }
536  if ( atom_required_in_active_site_[ jj_restype_id ] && ! active_site_grid().occupied( jjloc ) ) {
537  ii_good = false;
538  break;
539  }
540 
541  for ( Size kk = 1; kk <= min_sep_d2_from_upstream_atoms_[ jj_restype_id ].size(); ++kk ) {
542  if ( jjloc.distance_squared( upstream_residue.xyz( min_sep_d2_from_upstream_atoms_[ jj_restype_id ][ kk ].first ))
543  < min_sep_d2_from_upstream_atoms_[ jj_restype_id ][ kk ].second ) {
544  //std::cout << "collision between " << downstream_restype_->atom_name( at3_frame_id_2_restype_id_[ jj ] );
545  //std::cout << " on " << downstream_restype_->name() << " with ";
546  //std::cout << upstream_restype_->atom_name( min_sep_d2_from_upstream_atoms_[ jj ][ kk ].first ) << " on " << upstream_restype_->name() << std::endl;
547  ii_good = false;
548  break;
549  }
550  }
551  }
552 
553  if ( ! ii_good ) continue;
554 
555  /// Check the atoms we require to be in the active site, but which are not used in
556  /// collision detection
557  for ( Size jj = 1; jj <= non_collision_detection_atoms_reqd_in_active_site_.size(); ++jj ) {
559  Vector const jjloc = lig_conformers_[ ii_conf_id ]->coordinate_in_D3_frame( jj_restype_id, atom3_frame );
560 
561  if ( ! active_site_grid().occupied( jjloc ) ) {
562  ii_good = false;
563  break;
564  }
565  }
566 
567  if ( ! ii_good ) continue;
568 
569  Real6 global_coordinate = lig_conformers_[ ii_conf_id ]->global_orientation_from_frame3( atom3_frame );
570 
571  /// Check, if we're past the first round of hit building, that this orientation's
572  /// bin in 6D is not empty. If the bin is empty, then there is no way this
573  /// ligand placement could result in a match. Do not return this orientation as a hit.
574  //std::cout << "global coordinate: ";
575  //for ( Size jj = 1; jj <= 6; ++jj ) { std::cout << global_coordinate[ jj ] << " ";}
576  //std::cout << std::endl;
577 
578  if ( occ_space_set() && ! occ_space().match_possible_for_hit_geometry( global_coordinate ) ) {
579  continue;
580  }
581 
582  /// We have a hit!
583  //std::cout << "HIT!" << std::endl;
584 
585  Hit hit;
586  hit.first()[ 1 ] = scaffold_build_point_id;
587  hit.first()[ 2 ] = upstream_conf_id;
588  hit.first()[ 3 ] = external_geometry_id;
589  hit.first()[ 4 ] = ii_conf_id;
590  hit.second() = global_coordinate;
591 
592 
593  hitlist.push_back( hit ); /// new called here -- otherwise, nothing has been allocated on the heap since the Dunbrack rotamers
594  //break at the first hit
595  break;
596  }
597 
598  return hitlist;
599 }
600 
601 
602 void
604 {
605  runtime_assert( bbgrid_set() );
606  runtime_assert( lig_conformers_[ 1 ] );
607 
608  for ( Size ii = 1; ii <= lig_conformers_[ 1 ]->n_collision_check_atoms(); ++ii ) {
609  Size ii_restype_id = lig_conformers_[ 1 ]->collision_check_id_2_restype_id( ii );
610 
611  ProbeRadius ii_rad = atom_radii_[ ii_restype_id ];
612  for ( Size jj = 1; jj <= min_sep_d2_from_upstream_atoms_[ ii_restype_id ].size(); ++jj ) {
613  Size upstream_atom_id = min_sep_d2_from_upstream_atoms_[ ii_restype_id ][ jj ].first;
614  ProbeRadius jj_rad = probe_radius_for_atom_type( upstream_restype_->atom( upstream_atom_id ).atom_type_index() );
615 
616  Real dis = bbgrid().required_separation_distance( ii_rad, jj_rad );
617  min_sep_d2_from_upstream_atoms_[ ii_restype_id ][ jj ].second = dis*dis;
618  }
619  }
620 
621 }
622 
623 void
625 {
626  // Retrieve the rotamer library for this ligand, and create a LigandConformer object for each
627  // rotamer in the library. Make sure that the orientation-atom geometry and the
628  // D1, D2, and D3 geometry is the same for all input conformations.
629 
630  using namespace core;
631  using namespace core::conformation;
632  using namespace core::scoring;
633  using namespace core::pack::dunbrack;
634 
636  SingleResidueRotamerLibraryCAP res_rotlib( rotlib.get_rsd_library( residue.type() ) );
637 
638  if ( res_rotlib != 0 ) {
639  /// stoopid
640  /// typedef utility::pointer::access_ptr< SingleLigandRotamerLibrary const > SingleLigandRotamerLibraryCAP;
641 
642  SingleLigandRotamerLibraryCAP lig_rotlib( dynamic_cast< SingleLigandRotamerLibrary const * > ( res_rotlib.get() ));
643 
644  if ( lig_rotlib == 0 ) {
645  utility_exit_with_message( "Failed to retrieve a ligand rotamer library for "
646  + residue.name() + ". Did you mean to remove the -match::enumerate_ligand_rotamers flag from your command line?");
647  }
648 
649  Size const nligrots = lig_rotlib->get_rotamers().size();
650  if ( nligrots == 0 ) {
651  utility_exit_with_message( "Ligand rotamer library for " + residue.name() + " has 0 rotamers." );
652  }
653 
654  TR << "Found " << nligrots << " rotamers for " << residue.name() << std::endl;
655  //std::cout << "APL DEBUG LigandConformerBuilder" << this << std::endl;
656 
657  conformer_group_indices_.resize( nligrots );
658  conformer_group_for_conformer_.resize( nligrots );
659  lig_conformers_.resize( nligrots );
660 
661  if ( idealize_conformers_ ) {
662 
663  TR << "Idealizing ligand rotamers" << std::endl;
664 
665  pose::Pose ligpose;
666  ligpose.append_residue_by_jump( residue, 1 );
667 
668  for ( Size ii = 1; ii <= nligrots; ++ii ) {
669  conformer_group_indices_[ ii ].resize( 1 );
670  conformer_group_indices_[ ii ][ 1 ] = ii;
673  lig_conformers_[ ii ]->ignore_h_collisions( ignore_h_collisions_ );
674 
675  ligpose.replace_residue( 1, *lig_rotlib->get_rotamers()[ ii ], false );
676  idealize::IdealizeMover idealizer;
677  idealizer.report_CA_rmsd( false );
678  idealizer.apply( ligpose );
679 
680  Real rms( 0.0 );
681  for ( Size jj = 1; jj <= residue.nheavyatoms(); ++jj ) {
682  rms += lig_rotlib->get_rotamers()[ ii ]->xyz(jj).distance_squared( ligpose.residue(1).xyz(jj) );
683  }
684  Real rms_this_rot( std::sqrt( rms ) / residue.nheavyatoms() );
685  if( rms_this_rot >= 0.1 ) TR << "WARNING: Ligand rotamer " << ii << " has idealized RMS of " << rms_this_rot <<". Usually this number is < 0.1. Check whether ligand rotamers have the same bond lengths/bond angles as specified in the ligand .params file." << std::endl;
686 
687  lig_conformers_[ ii ]->initialize_from_residue(
688  atoms_123_[ 1 ], atoms_123_[ 2 ], atoms_123_[ 3 ],
690  ligpose.residue( 1 ) );
691  }
692  /// No error checking since we have idealized everything. The bond lengths and angles
693  /// that we need to be identical in all conformers (specifically, rotamers) so we're
694  /// safe.
695 
696  } else {
697 
698  for ( Size ii = 1; ii <= nligrots; ++ii ) {
699  conformer_group_indices_[ ii ].resize( 1 );
700  conformer_group_indices_[ ii ][ 1 ] = ii;
703  lig_conformers_[ ii ]->ignore_h_collisions( ignore_h_collisions_ );
704  lig_conformers_[ ii ]->initialize_from_residue(
705  atoms_123_[ 1 ], atoms_123_[ 2 ], atoms_123_[ 3 ],
707  * lig_rotlib->get_rotamers()[ ii ] );
708  }
709 
710  /// Error checking. Make sure that the geometries specified in the input pdb files
711  /// are in agreement between the various rotamers for atoms D1 D2 and D3 as well as
712  /// for orientation atoms 1, 2 and 3. PDB files are terribly low resolution, so we
713  /// there has to be sufficient tolerance in the error thresholds. What's a good amount?
714  /// 2 thousandths of an angstrom for distances should be enough; it's harder to say
715  /// with degrees. Currently, it's coded to tolerate only a tenth of a degree disagreement.
716 
717  Real const conf1_d12( lig_conformers_[ 1 ]->atom1_atom2_distance());
718  Real const conf1_d23( lig_conformers_[ 1 ]->atom2_atom3_distance());
719  Real const conf1_ang123( lig_conformers_[ 1 ]->atom1_atom2_atom3_angle());
720 
721  Real const conf1_oat_d12( lig_conformers_[ 1 ]->oatom1_oatom2_distance());
722  Real const conf1_oat_d23( lig_conformers_[ 1 ]->oatom2_oatom3_distance());
723  Real const conf1_oat_ang123( lig_conformers_[ 1 ]->oatom1_oatom2_oatom3_angle());
724 
725  Real const distance_tolerance = 2e-3;
726  Real const angle_tolerance = 1e-1;
727 
728  for ( Size ii = 2; ii <= nligrots; ++ii ) {
729 
730  if ( std::abs( lig_conformers_[ ii ]->atom1_atom2_distance() - conf1_d12 ) > distance_tolerance ) {
731  utility_exit_with_message( "Ligand rotamers disagree on distances between atoms "
732  + utility::trim( residue.atom_name( atoms_123_[ 1 ] ) ) + " and "
733  + utility::trim( residue.atom_name( atoms_123_[ 2 ] ) ) + ": "
734  + utility::to_string( conf1_d12 ) + " vs "
735  + utility::to_string( lig_conformers_[ ii ]->atom1_atom2_distance() )
736  + " for ligand rotamers #1 vs #" + utility::to_string( ii ) );
737  }
738  if ( std::abs( lig_conformers_[ ii ]->atom2_atom3_distance() - conf1_d23 ) > distance_tolerance ) {
739  utility_exit_with_message( "Ligand rotamers disagree on distances between atoms "
740  + utility::trim( residue.atom_name( atoms_123_[ 2 ] ) ) + " and "
741  + utility::trim( residue.atom_name( atoms_123_[ 3 ] ) ) + ": "
742  + utility::to_string( conf1_d23 ) + " vs "
743  + utility::to_string( lig_conformers_[ ii ]->atom2_atom3_distance() )
744  + " for ligand rotamers #1 vs #" + utility::to_string( ii ) );
745  }
746  if ( std::abs( lig_conformers_[ ii ]->atom1_atom2_atom3_angle() - conf1_ang123 ) > angle_tolerance ) {
747  utility_exit_with_message( "Ligand rotamers disagree on the angle between atoms "
748  + utility::trim( residue.atom_name( atoms_123_[ 1 ] ) ) + ", "
749  + utility::trim( residue.atom_name( atoms_123_[ 2 ] ) ) + " and "
750  + utility::trim( residue.atom_name( atoms_123_[ 3 ] ) ) + ": "
751  + utility::to_string( conf1_ang123 ) + " vs "
752  + utility::to_string( lig_conformers_[ ii ]->atom1_atom2_atom3_angle() )
753  + " for ligand rotamers #1 vs #" + utility::to_string( ii ) );
754  }
755 
756  if ( std::abs( lig_conformers_[ ii ]->oatom1_oatom2_distance() - conf1_oat_d12 ) > distance_tolerance ) {
757  utility_exit_with_message( "Ligand rotamers disagree on distances between atoms "
758  + utility::trim( residue.atom_name( orientation_atoms_[ 1 ] ) ) + " and "
759  + utility::trim( residue.atom_name( orientation_atoms_[ 2 ] ) ) + ": "
760  + utility::to_string( conf1_oat_d12 ) + " vs "
761  + utility::to_string( lig_conformers_[ ii ]->oatom1_oatom2_distance() )
762  + " for ligand rotamers #1 vs #" + utility::to_string( ii ) );
763  }
764  if ( std::abs( lig_conformers_[ ii ]->oatom2_oatom3_distance() - conf1_oat_d23 ) > distance_tolerance ) {
765  utility_exit_with_message( "Ligand rotamers disagree on distances between atoms "
766  + utility::trim( residue.atom_name( orientation_atoms_[ 2 ] ) ) + " and "
767  + utility::trim( residue.atom_name( orientation_atoms_[ 3 ] ) ) + ": "
768  + utility::to_string( conf1_oat_d23 ) + " vs "
769  + utility::to_string( lig_conformers_[ ii ]->oatom2_oatom3_distance() )
770  + " for ligand rotamers #1 vs #" + utility::to_string( ii ) );
771  }
772  if ( std::abs( lig_conformers_[ ii ]->oatom1_oatom2_oatom3_angle() - conf1_oat_ang123 ) > angle_tolerance ) {
773  utility_exit_with_message( "Ligand rotamers disagree on the angle between atoms "
774  + utility::trim( residue.atom_name( orientation_atoms_[ 1 ] ) ) + ", "
775  + utility::trim( residue.atom_name( orientation_atoms_[ 2 ] ) ) + " and "
776  + utility::trim( residue.atom_name( orientation_atoms_[ 3 ] ) ) + ": "
777  + utility::to_string( conf1_oat_ang123 ) + " vs "
778  + utility::to_string( lig_conformers_[ ii ]->oatom1_oatom2_oatom3_angle() )
779  + " for ligand rotamers #1 vs #" + utility::to_string( ii ) );
780  }
781  } // else ! idealize_conformers_
782  }
783  } else {
784  TR << "No ligand rotamer library found, matching with geometry specified form .params file." << std::endl;
785 
786  conformer_group_indices_.resize( 1 );
788  lig_conformers_.resize( 1 );
789  conformer_group_indices_[ 1 ].resize( 1 );
790  conformer_group_indices_[ 1 ][ 1 ] = 1;
793  lig_conformers_[ 1 ]->ignore_h_collisions( ignore_h_collisions_ );
794  lig_conformers_[ 1 ]->initialize_from_residue(
795  atoms_123_[ 1 ], atoms_123_[ 2 ], atoms_123_[ 3 ],
797  residue );
798 
799  //utility_exit_with_message( "Failed to find ligand rotamer library for " +
800  //residue.name() + ". Did you mean to remove the -match::enumerate_ligand_rotamers flag from your command line?" );
801  }
802 
803 }
804 
807 {
808  return lig_conformers_[ conf_id ] ;
809 }
810 
811 //utility::vector1< utility::vector1< std::pair< core::Size, core::Real > > >
812 //LigandConformerBuilder::get_min_sep_d2_from_upstream_atoms() const
813 //{
814 // return min_sep_d2_from_upstream_atoms_;
815 //}
816 
819 {
820  return upstream_restype_;
821 }
822 
823 }
824 }
825 }