Rosetta 3.5
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
EnzConstraintParameters.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 IO-functionality for enzyme design constraints
11 /// @brief
12 /// @author Florian Richter, floric@u.washington.edu
13 
14 // Unit headers
16 
17 
18 // Package headers
23 
24 // AUTO-REMOVED #include <protocols/toolbox/match_enzdes_util/EnzConstraintIO.hh>
25 #include <core/scoring/Energies.hh>
36 #include <core/scoring/constraints/BoundConstraint.hh> //need function in this file
37 
38 // Project headers
39 #include <core/types.hh>
41 #include <core/chemical/ChemicalManager.hh> //need for changing residue type sets
42 #include <core/chemical/ResidueTypeSet.hh> //have to include complete file
43 #include <core/chemical/Patch.hh> //needed for residue type base name function
44  //needed for adding variant types
45 // AUTO-REMOVED #include <core/chemical/residue_io.hh> //needed for writing out .params files
46 #include <core/pack/dunbrack/SingleLigandRotamerLibrary.hh> //needed for clean residue type modification
47 #include <core/pose/Pose.hh>
48 #include <core/pose/PDBInfo.hh>
49 #include <core/scoring/ScoreFunction.hh> //scoring ambiguous constraints
50 #include <core/id/AtomID.hh>
51 #include <core/pose/Remarks.hh> //reading remarks
52 #include <basic/options/option.hh> //options
54 
55 // Numeric headers
56 #include <numeric/constants.hh>
57 
58 // Utility Headers
59 // AUTO-REMOVED #include <utility/string_util.hh>
60 #include <iostream>
61 #include <string>
62 #include <sstream>
63 
64 #include <basic/Tracer.hh>
65 
66 // option key includes
67 
68 #include <basic/options/keys/enzdes.OptionKeys.gen.hh>
69 
70 #include <core/pose/util.hh>
72 #include <utility/vector1.hh>
73 
74 #include <utility/string_util.hh>
75 
76 
77 static basic::Tracer tr("protocols.toolbox.match_enzdes_util.EnzConstraintParameters");
78 
79 namespace protocols {
80 namespace toolbox{
81 namespace match_enzdes_util {
82 
83 using namespace ObjexxFCL;
84 
86  std::string resA_base_in,
87  std::string resB_base_in,
88  std::string resA_var_in,
89  std::string resB_var_in,
90  core::Size Apos_in,
91  core::Size Bpos_in,
93 ) : ReferenceCount(),
94  resA_basename_(resA_base_in), resB_basename_(resB_base_in),
95  resA_varname_(resA_var_in), resB_varname_(resB_var_in),
96  resA_modname_(resA_base_in + resA_var_in), resB_modname_(resB_base_in+resB_var_in),
97  resA_seqpos_(Apos_in), resB_seqpos_(Bpos_in),
98  restype_set_(restype_set_in)
99 {}
100 
101 
103  : ReferenceCount(),
104  resA_basename_(other.resA_basename_), resB_basename_(other.resB_basename_),
105  resA_varname_(other.resA_varname_), resB_varname_(other.resB_varname_),
106  resA_modname_(other.resA_modname_), resB_modname_(other.resB_modname_),
107  resA_seqpos_(other.resA_seqpos_), resB_seqpos_(other.resB_seqpos_),
108  restype_set_(other.restype_set_)
109 {}
110 
112 
113 void
115  core::pose::Pose & pose
116 ) const {
117 
118  //first check whether the right residue types are still at their positions
120  utility_exit_with_message("Error when trying to remove covalent connection: for resA, pose residue basename should be "+resA_modname_+", but is "+residue_type_base_name( pose.residue_type(resA_seqpos_))+"\n.");
121  }
122 
124  utility_exit_with_message("Error when trying to remove covalent connection: for resB, pose residue basename should be "+resB_modname_+", but is "+residue_type_base_name( pose.residue_type(resB_seqpos_))+"\n.");
125  }
126 
127  core::conformation::Residue newA_res( restype_set_->name_map(resA_basename_), true);
128 
131 
132  for(core::Size var = 1; var <= curA_variants.size(); var++){
133  if( curA_variants[ var ] != resA_varname_ ){
134  core::pose::add_variant_type_to_pose_residue( pose, curA_variants[ var ], resA_seqpos_ );
135  }
136  }
137 
138  core::conformation::Residue newB_res( restype_set_->name_map(resB_basename_), true);
139 
142 
143  for(core::Size var = 1; var <= curB_variants.size(); var++){
144  if( curB_variants[ var ] != resB_varname_ ){
145  core::pose::add_variant_type_to_pose_residue( pose, curB_variants[ var ], resB_seqpos_ );
146  }
147  }
148  //std::cerr << "done removing covalent connection between res " << resA_seqpos_ << " and res " << resB_seqpos_ << std::endl;
149 }
150 
151 
152 void
154  core::id::SequenceMapping const & smap
155 ){
156  resA_seqpos_ = smap[resA_seqpos_];
157  resB_seqpos_ = smap[resB_seqpos_];
158 
159  if( (resA_seqpos_ == 0) || (resB_seqpos_ == 0 ) ) utility_exit_with_message("A covalently constrained residue apparently got deleted from the pose");
160 }
161 
163  core::Size cst_block,
164  core::chemical::ResidueTypeSetCAP src_restype_set,
165  EnzConstraintIOCAP src_enz_io
166 )
167 : utility::pointer::ReferenceCount(),
168  mcfi_(NULL),
169  ndisAB_(0), nangleA_(0), nangleB_(0), ntorsionA_(0), ntorsionB_(0), ntorsionAB_(0),
170  restype_set_( src_restype_set), enz_io_( src_enz_io ), cst_block_(cst_block)
171 {
172  resA_ = new EnzCstTemplateRes(src_restype_set, this);
173  resA_->set_param_index( 1 );
174  resB_ = new EnzCstTemplateRes(src_restype_set, this);
175  resB_->set_param_index( 2 );
176  disAB_ = NULL; angleA_ = NULL; angleB_ = NULL; torsionA_ = NULL; torsionB_ = NULL; torsionAB_ = NULL;
177  is_covalent_ = false;
178  empty_ = true;
179 }
181 : utility::pointer::ReferenceCount(),
182  resA_(NULL), resB_(NULL), mcfi_(NULL),disAB_(NULL),
183  angleA_(NULL), angleB_(NULL), torsionA_(NULL),
184  torsionB_(NULL), torsionAB_(NULL),
185  ndisAB_(0), nangleA_(0), nangleB_(0), ntorsionA_(0),
186  ntorsionB_(0), ntorsionAB_(0),
187  is_covalent_(false), empty_(true),
188  restype_set_( NULL), enz_io_( NULL), cst_block_(0)
189 {}
191 
192 /// @brief copy constructor
193 /// @brief WARNING: currently this probably doesn't copy the functions or active pose constraints
195 :
196  utility::pointer::ReferenceCount(),
197  mcfi_(other.mcfi_),
198  disAB_(other.disAB_), angleA_(other.angleA_), angleB_(other.angleB_),
199  torsionA_(other.torsionA_), torsionB_(other.torsionB_), torsionAB_(other.torsionAB_),
200  ndisAB_(other.ndisAB_), nangleA_(other.nangleA_), nangleB_(other.nangleB_),
201  ntorsionA_(other.ntorsionA_), ntorsionB_(other.ntorsionB_), ntorsionAB_(other.ntorsionAB_),
202  is_covalent_(other.is_covalent_), empty_(other.empty_),
203  restype_set_( other.restype_set_),
204  cst_block_(other.cst_block_) //debatable whether this should be kept, but it's useful
205 {
206 
207  resA_ = new EnzCstTemplateRes( other.resA_, this );
208  resB_ = new EnzCstTemplateRes( other.resB_, this );
209  // we want an independent copy of the object, so the original reference is erased
210  enz_io_ = NULL;
211 }
212 
213 
214 void
217 {
218  //if this mcfi has been previously set,
219  //we don't need to do anything
220  if( mcfi_ == mcfi ) return;
221 
222  mcfi_ = mcfi;
223 
224  resA_ = new EnzCstTemplateRes( mcfi_->enz_cst_template_res( 1 ), this );
225  resA_->set_param_index( 1 );
226  resB_ = new EnzCstTemplateRes( mcfi_->enz_cst_template_res( 2 ), this );
227  resB_->set_param_index( 2 );
228  resA_->identical_info_consistency_check();
229  resB_->identical_info_consistency_check();
230 
236 
237  //the distance is special, we'll do it explicitly
238  if( mcfi_->dis_U1D1() ){
239  ndisAB_ = mcfi_->dis_U1D1()->ideal_val();
240 
241  core::Real min_dis = std::max(0.0, ndisAB_ - mcfi_->dis_U1D1()->tolerance() );
242  core::Real max_dis = ndisAB_ + mcfi_->dis_U1D1()->tolerance();
243  core::Real force_k_dis = mcfi_->dis_U1D1()->force_const();
244 
246  min_dis, max_dis, sqrt(1/ force_k_dis), "dis");
247 
248  //if( mcfi_->dis_U1D1()->periodicity() == 1.0 ) is_covalent_ = true;
249  if( mcfi->is_covalent() ) is_covalent_ = true;
250  else is_covalent_ = false;
251  }
252 }
253 
254 
258  core::Real & ideal_val)
259 {
260 
261  core::Real const rad_per_deg = numeric::constants::f::degrees_to_radians;
262  core::Real const twopi = numeric::constants::f::pi_2;
263 
264  core::scoring::constraints::FuncOP to_return( NULL );
265 
266  //check if this gsi has a force constant resp. if it even exists
267  //if not, return right away. this will lead to no constraints being produced
268  if( !gsi ) return to_return;
269 
270  ideal_val = gsi->ideal_val() * rad_per_deg;
271 
272  if( gsi->force_const() == 0.0 ) return to_return;
273 
274  core::Real x0 = gsi->ideal_val() * rad_per_deg;
275  core::Real x_sd = gsi->tolerance() * rad_per_deg;
276  core::Real period_rad = gsi->periodicity() * rad_per_deg;
277 
278  if( gsi->function_tag() == "PERIODIC" ){
279 
280  if( ( gsi->tag() == "angle_A:" ) || ( gsi->tag() == "angle_B:" ) ){
281  std::cerr << "Error in cstfile reading: periodic functions are not supported for angle constraints." << std::endl;
282  utility::exit( EXIT_FAILURE, __FILE__, __LINE__);
283  }
284 
285  if(x_sd > 0.0){
286  tr.Info << "WARNING: Constraint specified for tag " << gsi->tag() << " requests a periodic function. Standard-Deviation/tolerance is meaningless in this case. The tolerance value of " << gsi->tolerance() << " that you specified will be ignored!" << std::endl;
287  }
288 
289  to_return = new core::scoring::constraints::CharmmPeriodicFunc(x0, gsi->force_const(), twopi/period_rad);
290 
291  }
292 
293  else{
294  to_return = new core::scoring::constraints::OffsetPeriodicBoundFunc(-x_sd,x_sd, sqrt( 1/gsi->force_const() ), "offsetperiodicbound", period_rad, x0);
295  }
296 
297  return to_return;
298 
299 }
300 
301 /// @brief process the information in template residues and the func op pointers to add
302 /// @brief to the constraint set in the right format
303 void
305  core::pose::Pose & pose,
307 {
308 
309  using namespace core::scoring::constraints;
310 
311  //sequentially process the six possible constraints
312  bool all_constraints_empty = true;
313 
314  EnzdesCstParamCacheOP param_cache(protocols::toolbox::match_enzdes_util::get_enzdes_observer( pose )->cst_cache()->param_cache( cst_block_ ) );
315  runtime_assert( param_cache );
316  param_cache->active_pose_constraints_.clear();
317  if( param_cache->covalent_connections_.size() != 0 ) remove_covalent_connections_from_pose( pose );
318 
319  Size number_constraints_added(0);
320 
321  //std::cerr << "generating constraints for block " << cst_block_ << ". There are " << resA_->respos_map_size() << " positions in resA and " << resB_->respos_map_size() << " positions in resB." << std::endl;
322 
323  for (std::map< Size, EnzCstTemplateResAtomsOP >::const_iterator resApos_it = param_cache->template_res_cache_[1]->seqpos_map_begin(), resApos_end = param_cache->template_res_cache_[1]->seqpos_map_end(); resApos_it != resApos_end; ++resApos_it){
324 
325  for (std::map< Size, EnzCstTemplateResAtomsOP >::const_iterator resBpos_it = param_cache->template_res_cache_[2]->seqpos_map_begin(), resBpos_end = param_cache->template_res_cache_[2]->seqpos_map_end(); resBpos_it != resBpos_end; ++resBpos_it){
326 
327  //std::cerr << "making stuff between resA " << resApos_it->first << " and resB " << resBpos_it->first << std::endl;
328 
329  Size ambig_resA(resApos_it->second->atom1_.size()), ambig_resB(resBpos_it->second->atom1_.size());
330 
331  Size number_ambiguous_constraints = ambig_resA * ambig_resB;
332  if( number_ambiguous_constraints != 1){
333  tr.Info << "Constraint specified between residues " << resApos_it->first << " and " << resBpos_it->first << " is ambiguous, " << number_ambiguous_constraints << " different possibilities ( " << ambig_resA << " for " << resApos_it->first << ", " << ambig_resB << " for " << resBpos_it->first << ".)" << std::endl;
334  }
335 
336 
338 
339  for( Size ambig_resA_count(0); ambig_resA_count < ambig_resA; ambig_resA_count++){
340 
341  for( Size ambig_resB_count(0); ambig_resB_count < ambig_resB; ambig_resB_count++){
342 
343 
344  utility::vector1< ConstraintCOP > this_pair_csts;
345 
346  if(disAB_ != 0){
347  all_constraints_empty = false;
348  this_pair_csts.push_back( new AtomPairConstraint( resApos_it->second->atom1_[ambig_resA_count], resBpos_it->second->atom1_[ambig_resB_count], disAB_) );
349  number_constraints_added++;
350 
351  if(basic::options::option[basic::options::OptionKeys::enzdes::enz_debug] )
352  {
353  std::string at1name = pose.residue(resApos_it->first).atom_name(resApos_it->second->atom1_[ambig_resA_count].atomno());
354  std::string at2name = pose.residue(resBpos_it->first).atom_name(resBpos_it->second->atom1_[ambig_resB_count].atomno());
355  tr << "adding distance constraint between atom " << at1name << "of res " << resApos_it->first << " and atom " << at2name << " of resi " << resBpos_it->first << "." << std::endl;
356  }
357  //debug stuff over
358  }
359 
360  if(angleA_ != 0){
361  all_constraints_empty = false;
362  this_pair_csts.push_back( new AngleConstraint( resApos_it->second->atom2_[ambig_resA_count], resApos_it->second->atom1_[ambig_resA_count], resBpos_it->second->atom1_[ambig_resB_count], angleA_) );
363  number_constraints_added++;
364 
365  //debug stuff
366  if(basic::options::option[basic::options::OptionKeys::enzdes::enz_debug] )
367  {
368  std::string at1name = pose.residue(resApos_it->first).atom_name(resApos_it->second->atom2_[ambig_resA_count].atomno());
369  std::string at2name = pose.residue(resApos_it->first).atom_name(resApos_it->second->atom1_[ambig_resA_count].atomno());
370  std::string at3name = pose.residue(resBpos_it->first).atom_name(resBpos_it->second->atom1_[ambig_resB_count].atomno());
371  tr << "adding angle constraint between atoms " << at1name << " and " << at2name << "of res " << resApos_it->first << " and atom " << at3name << " of resi " << resBpos_it->first << "." << std::endl;
372  }
373  //debug stuff over
374  }
375 
376  if(angleB_ != 0){
377  all_constraints_empty = false;
378  this_pair_csts.push_back( new AngleConstraint( resApos_it->second->atom1_[ambig_resA_count], resBpos_it->second->atom1_[ambig_resB_count], resBpos_it->second->atom2_[ambig_resB_count], angleB_) );
379  number_constraints_added++;
380 
381  //debug stuff
382  if(basic::options::option[basic::options::OptionKeys::enzdes::enz_debug] )
383  {
384  std::string at1name = pose.residue(resApos_it->first).atom_name(resApos_it->second->atom1_[ambig_resA_count].atomno());
385  std::string at2name = pose.residue(resBpos_it->first).atom_name(resBpos_it->second->atom1_[ambig_resB_count].atomno());
386  std::string at3name = pose.residue(resBpos_it->first).atom_name(resBpos_it->second->atom2_[ambig_resB_count].atomno());
387  tr << "adding angle constraint between atoms " << at1name << "of res " << resApos_it->first << " and atom " << at2name << " and " << at3name << " of resi " << resBpos_it->first << "." << std::endl;
388  }
389  //debug stuff over
390 
391  }
392 
393  if(torsionA_ != 0){
394  all_constraints_empty = false;
395  this_pair_csts.push_back( new DihedralConstraint( resApos_it->second->atom3_[ambig_resA_count], resApos_it->second->atom2_[ambig_resA_count], resApos_it->second->atom1_[ambig_resA_count], resBpos_it->second->atom1_[ambig_resB_count], torsionA_) );
396  number_constraints_added++;
397 
398  //debug stuff
399  if(basic::options::option[basic::options::OptionKeys::enzdes::enz_debug] )
400  {
401  std::string at1name = pose.residue(resApos_it->first).atom_name(resApos_it->second->atom3_[ambig_resA_count].atomno());
402  std::string at2name = pose.residue(resApos_it->first).atom_name(resApos_it->second->atom2_[ambig_resA_count].atomno());
403  std::string at3name = pose.residue(resApos_it->first).atom_name(resApos_it->second->atom1_[ambig_resA_count].atomno());
404  std::string at4name = pose.residue(resBpos_it->first).atom_name(resBpos_it->second->atom1_[ambig_resB_count].atomno());
405  tr << "adding dihedral constraint between atoms " << at1name << " and " << at2name << " and " << at3name << " of res " << resApos_it->first << " and atom " << at4name << " of resi " << resBpos_it->first << "." << std::endl;
406  }
407  //debug stuff over
408 
409  }
410 
411  if(torsionB_ != 0){
412  all_constraints_empty = false;
413  this_pair_csts.push_back( new DihedralConstraint( resApos_it->second->atom1_[ambig_resA_count], resBpos_it->second->atom1_[ambig_resB_count], resBpos_it->second->atom2_[ambig_resB_count], resBpos_it->second->atom3_[ambig_resB_count], torsionB_) );
414  number_constraints_added++;
415 
416  //debug stuff
417  if(basic::options::option[basic::options::OptionKeys::enzdes::enz_debug] )
418  {
419  std::string at1name = pose.residue(resApos_it->first).atom_name(resApos_it->second->atom1_[ambig_resA_count].atomno());
420  std::string at2name = pose.residue(resBpos_it->first).atom_name(resBpos_it->second->atom1_[ambig_resB_count].atomno());
421  std::string at3name = pose.residue(resBpos_it->first).atom_name(resBpos_it->second->atom2_[ambig_resB_count].atomno());
422  std::string at4name = pose.residue(resBpos_it->first).atom_name(resBpos_it->second->atom3_[ambig_resB_count].atomno());
423  tr << "adding dihedral constraint between atoms " << at1name << " of res " << resApos_it->first << " and " << at2name << " and " << at3name << " and " << at4name << " of resi " << resBpos_it->first << "." << std::endl;
424  }
425  //debug stuff over
426  }
427 
428  if(torsionAB_ != 0){
429  all_constraints_empty = false;
430  this_pair_csts.push_back( new DihedralConstraint( resApos_it->second->atom2_[ambig_resA_count], resApos_it->second->atom1_[ambig_resA_count], resBpos_it->second->atom1_[ambig_resB_count], resBpos_it->second->atom2_[ambig_resB_count], torsionAB_) );
431  number_constraints_added++;
432  }
433 
434  if( (this_pair_csts.size() > 0 ) && ( number_ambiguous_constraints == 1) ){
435 
436  param_cache->active_pose_constraints_.push_back( new MultiConstraint(this_pair_csts) );
437  }
438  else if( (this_pair_csts.size() > 0) && ( number_ambiguous_constraints > 1) ) {
439  ambig_csts.push_back( new MultiConstraint(this_pair_csts) );
440  }
441  } //ambig_resB_count
442  } //ambig_resA_count
443 
444  if( ambig_csts.size() > 0 ) {
445  //cstset->show( tr );
446 
447  if( is_covalent_ ) {
448  //we first have to resolve the ambiguity to make the covalent connection
449  //strategy: score each constraint in succession, remember which one is the lowest
450  tr.Info << "The covalent constraint specified for this block is ambiguous. ";
451  tr.Info << "Ambiguity will be resolved according to the best constraint in the input pose." << std::endl;
452  Size n_best_constraint = determine_best_constraint( pose, scofx, ambig_csts );
453 
454  param_cache->active_pose_constraints_.push_back( ambig_csts[ n_best_constraint ] );
455 
456  //additional feat: we have to map the information about the best constraint back to what
457  //atoms it contains, in the context of where these atoms are saved in the EnzCstTemplateRes object
458  Size best_resA_At(0);
459  Size best_resB_At(0);
460  Size n_mod_ambigA = n_best_constraint % ambig_resA;
461  if( n_mod_ambigA == 0) {
462  best_resA_At = ambig_resA - 1;
463  best_resB_At = ( n_best_constraint / ambig_resA ) - 1;
464  }
465  else{
466  best_resA_At = n_mod_ambigA - 1;
467  best_resB_At = n_best_constraint / ambig_resA; //integer division
468  }
469  make_constraint_covalent( pose, resApos_it->first, resBpos_it->first, best_resA_At, best_resB_At);
470 
471  }
472  else{
473  if(basic::options::option[basic::options::OptionKeys::enzdes::enz_debug] ){
474  tr.Info << "Adding an ambiguous constraint containing " << ambig_csts.size() << "constraints." << std::endl;
475  }
476  param_cache->active_pose_constraints_.push_back( new AmbiguousConstraint(ambig_csts) );
477  }
478  }
479  else if( is_covalent_ ){
480  make_constraint_covalent( pose, resApos_it->first, resBpos_it->first, 0, 0);
481  } //if is_covalent_
482 
483 
484  }//iterator over the residue numbers for template residue B
485  }//iterator over the residue numbers for template residue A
486 
487  empty_ = all_constraints_empty;
488 
489  if(all_constraints_empty) {
490  tr.Info << "Warning: no constraints were added for constraint block " << cst_block_ << "." << std::endl;
491  }
492  else {
493  tr.Info << "for block " << cst_block_ << ", " << number_constraints_added << " newly generated constraints were added " << std::endl;
494  }
495 
496 } //add_constraints_to_cst_set
497 
498 
499 
500 void
502  core::pose::Pose & pose,
503  Size resA_pos,
504  Size resB_pos,
505  Size resA_At,
506  Size resB_At) const
507 {
508  using namespace core::chemical;
509 
510  if(basic::options::option[basic::options::OptionKeys::enzdes::enz_debug] ){
511  pose.dump_pdb("bef_resmod.pdb");
512  }
513  std::string resA_base = residue_type_base_name( pose.residue_type(resA_pos) );
514  std::string resB_base = residue_type_base_name( pose.residue_type(resB_pos) );
515  std::string resA_var, resB_var;
516 
517  make_constraint_covalent_helper( pose, resA_, resA_pos, resA_At, ntorsionA_, nangleA_, disAB_, resA_var );
518 
519  make_constraint_covalent_helper( pose, resB_, resB_pos, resB_At, ntorsionB_, nangleB_, disAB_, resB_var );
520 
521  if(basic::options::option[basic::options::OptionKeys::enzdes::enz_debug] ){
522  pose.dump_pdb("after_resmod.pdb");
523  }
524 
525  std::string resA_atomname = pose.residue( resA_pos ).atom_name( (resA_->get_template_atoms_at_pos(pose, resA_pos))->atom1_[resA_At].atomno());
526  std::string resB_atomname = pose.residue( resB_pos ).atom_name( (resB_->get_template_atoms_at_pos(pose, resB_pos))->atom1_[resB_At].atomno());
527 
528  tr.Debug << "Adding chemical bond between " << pose.residue( resA_pos ).name() << " " << (resA_->get_template_atoms_at_pos(pose, resA_pos))->atom1_[resA_At].atomno() << " "<< resA_pos << " " << resA_atomname << " and "
529  << pose.residue( resB_pos ).name() << " " << resB_pos << " " << (resB_->get_template_atoms_at_pos(pose, resB_pos))->atom1_[resB_At].atomno() << " " << resB_atomname << std::endl;
530 
532  resA_pos, resA_atomname,
533  resB_pos, resB_atomname
534  );
535  EnzdesCstParamCacheOP param_cache( protocols::toolbox::match_enzdes_util::get_enzdes_observer( pose )->cst_cache()->param_cache( cst_block_ ) );
536 
537  param_cache->covalent_connections_.push_back( new CovalentConnectionReplaceInfo(resA_base, resB_base, resA_var, resB_var, resA_pos, resB_pos, restype_set_ ) ); //new
538 
539 } //make_constraint_covalent
540 
541 
542 
543 
544 /// @brief helper function so stuff doesn't need to be written twice
545 void
547  core::pose::Pose & pose,
548  EnzCstTemplateResOP template_res,
549  core::Size res_pos,
550  core::Size Atpos,
551  core::Real itorsion,
552  core::Real iangle,
553  core::Real idis,
554  std::string & res_varname
555  ) const
556 {
557  //std::cout << "APL DEBUG EnzConstraintParameters.cc::make_constraint_covalent_helper begin" << std::endl;
558 
559  using namespace core::chemical;
560  using namespace core::pack::dunbrack;
561 
562  std::string res_atom = pose.residue(res_pos).atom_name( (template_res->get_template_atoms_at_pos(pose, res_pos) )->atom1_[Atpos].atomno() );
563 
564  //need to remove whitespace, why the f is this so clumsy in c++?!?
565  int whitespace_pos = res_atom.find(" ");
566  while( whitespace_pos != -1 ) {
567  res_atom.erase(whitespace_pos, 1 );
568  whitespace_pos = res_atom.find(" ");
569  }
570 
571  std::string current_pose_type_basename( residue_type_base_name( pose.residue_type(res_pos) ) );
572  std::string current_pose_type_patches_name( residue_type_all_patches_name( pose.residue_type(res_pos) ) );
573 
574  res_varname = "_connect" + res_atom;
575  {// scope
576  // Find a name for the new residue type / variant name that will be added to the existing
577  // residue so that, if the existing residue already has this variant type, then the
578  // new residue type will get one with a new name.
579  core::chemical::ResidueType const & currres( pose.residue_type( res_pos ));
580  Size count=0;
581  while ( true ) {
582  if ( count > 1000 ) {
583  utility_exit_with_message( "Encountered infinite loop trying to find a new variant name for residue type " + currres.name() + " in EnzConstraintParameters. Talk to Andrew.");
584  }
585  ++count;
586  if ( count == 1 ) {
587  if ( ! currres.has_variant_type( res_varname )) break;
588  } else {
589  res_varname = "_"+utility::to_string(count)+"connect"+res_atom;
590  if ( ! currres.has_variant_type( res_varname )) break;
591  }
592  }
593  }
594  std::string res_type_mod_name( current_pose_type_basename + res_varname + current_pose_type_patches_name );
595 
596  //check whether the modified residues have already been created earlier
597  if( !restype_set_->has_name(res_type_mod_name) ){
598 
599  //holy jesus, we have to change the residue type set.
600  //we not only need to clone, modify and add the residue type
601  //currently in the pose, but all similar ones (same basename )
602  //in the ResidueTypeSet. We also need to create a copy of the
603  // SingleLigandRotamerLibrary in case it exists.
604  //reminds me of open heart surgery...
605 
606  //the following line is necessary to ensure that a ligand rotamer library exists
607  //if this function is called before any scoring happened
608  RotamerLibrary::get_instance().get_rsd_library( pose.residue_type( res_pos ));
609 
610  SingleLigandRotamerLibraryOP new_lrots = NULL;
611  if( pose.residue_type(res_pos).is_ligand() &&
612  RotamerLibrary::get_instance().rsd_library_already_loaded( pose.residue_type(res_pos) ) ) {
613  new_lrots = new SingleLigandRotamerLibrary();
614  }
615 
617 
618  //first get all residue types that correspond to the type in question
619  ResidueTypeCOPs res_to_modify = mod_restype_set->name3_map( pose.residue_type(res_pos).name3() );
620 
621  for ( utility::vector1< ResidueTypeCOP >::iterator res_it = res_to_modify.begin(); res_it != res_to_modify.end(); ++res_it) {
622  std::string const base_name( residue_type_base_name( *(*res_it) ) );
623  //std::cerr << "contemplating modification of residuetype " << (*res_it)->name() << " with basename " << base_name << std::endl;
624 
625  if( current_pose_type_basename == base_name ){
626 
627  ResidueTypeOP mod_res;
628  core::Size con_res(0);
629  //std::cerr << " MODIFYING" << std::endl;
630  std::string patches_name( residue_type_all_patches_name( *(*res_it) ) );
631  std::string new_name( base_name + res_varname + patches_name );
632 
633  mod_res = (*res_it)->clone();
634  con_res = mod_res->add_residue_connection( res_atom );
635  mod_res->name( new_name );
636  assert( ! mod_res->has_variant_type( res_varname ) );
637  mod_res->add_variant_type( res_varname ); //necessary to restrict the packer to only use this residue variant in packing
638 
639  mod_res->set_icoor( "CONN"+string_of( con_res ), itorsion, iangle, idis, res_atom, pose.residue(res_pos).atom_name( (template_res->get_template_atoms_at_pos( pose, res_pos) )->atom2_[Atpos].atomno() ), pose.residue(res_pos).atom_name( (template_res->get_template_atoms_at_pos(pose, res_pos) )->atom3_[Atpos].atomno() ), true );
640 
641  //new_lrots is empty at the moment, but will be filled a couple of lines down
642  if( pose.residue_type( res_pos ).is_ligand() ) {
643  RotamerLibrary::get_instance().add_residue_library( *mod_res, new_lrots );
644  }
645 
646  //finalize again just to make sure
647  mod_res->nondefault(true);
648  mod_res->base_restype_name( base_name );
649  mod_res->finalize();
650 
651  mod_restype_set->add_residue_type( mod_res );
652  }
653  }
654 
655  //and last but not least we have to regenerate the rotamer library for the ligand
656  if( pose.residue_type( res_pos ).is_ligand() ) {
657 
659  static_cast< SingleLigandRotamerLibrary const * >
660  ( RotamerLibrary::get_instance().get_rsd_library( pose.residue_type( res_pos ))() ));
661 
662  if( old_lrots != 0 ){
663 
664  using namespace core::conformation;
665  utility::vector1< ResidueOP > new_rotamers;
666  new_rotamers.clear();
667  utility::vector1< ResidueOP > const old_rotamers = old_lrots->get_rotamers();
668 
669  //std::cerr << "old rotamer library has " << old_rotamers.size() << "members";
670  for( utility::vector1< ResidueOP>::const_iterator oldrot_it = old_rotamers.begin(); oldrot_it != old_rotamers.end(); ++oldrot_it){
671  ResidueOP new_rot_res = new Residue( restype_set_->name_map(res_type_mod_name), true);
672  //set the coordinates
673  //1. we go over the atoms of the NEW residue on purpose, to make sure that no atom gets skipped
674  for( core::Size at_ct = 1; at_ct <= new_rot_res->natoms(); at_ct++){
675  if( !(*oldrot_it)->has( new_rot_res->atom_name( at_ct ) ) ){
676  std::cerr << "Unexpected ERROR: when regenerating ligand rotamer library (for covalent constraints), one atom wasn't found in a template rotamer." << std::endl;
677  utility::exit( EXIT_FAILURE, __FILE__, __LINE__);
678  }
679  else{
680  new_rot_res->set_xyz( at_ct, (*oldrot_it)->xyz( new_rot_res->atom_name( at_ct ) ) );
681  }
682  }
683  //2. we also set the chis, to make sure everything is properly in place
684  new_rot_res->chi( (*oldrot_it)->chi() );
685 
686  new_rotamers.push_back( new_rot_res );
687  }
688  new_lrots->set_reference_energy( old_lrots->get_reference_energy() );
689  new_lrots->set_rotamers( new_rotamers );
690  //std::cerr << "new rotlibrary has " << new_lrots->get_rotamers().size() << " members." << std::endl;
691  }
692  }
693  }
694 
695  core::conformation::Residue new_res( restype_set_->name_map(res_type_mod_name), true);
696 
697  replace_residue_keeping_all_atom_positions( pose, new_res, res_pos );
698 
699  //std::cout << "APL DEBUG EnzConstraintParameters.cc::make_constraint_covalent_helper end" << std::endl;
700 
701 } //make_constraint_covalent_helper
702 
703 
704 
705 void
707 {
708  tr.Info << "parameters residue 1:" << std::endl;
709  resA_->show_params();
710  tr.Info << "parameters residue 2:" << std::endl;
711  resB_->show_params();
712 }
713 
714 void
716  core::pose::Pose & pose,
718 {
719  resA_->get_pose_data(pose);
720  resB_->get_pose_data(pose);
721  generate_active_pose_constraints( pose, scofx );
722 }
723 
724 
725 
726 /// @brief function to determine the lowest scoring constraint in a vector of input constraints
727 /// @brief there might be a slightly faster and slightly more complicated way to implement this,
728 /// @brief but since this function will only be called once per input pose (if it is called at all),
729 /// @brief it probably doesn't matter.
732  core::pose::Pose const & pose,
735 {
736 
737  if( candidate_csts.size() < 2 ){
738  std::cerr << "Error, this function should not be called with a constraint input vector containing less than 2 constraints. " << std::endl;
739  utility::exit( EXIT_FAILURE, __FILE__, __LINE__);
740  }
741 
742 
743  core::scoring::ScoreFunction helper_scofx;
744 
745  //need to score each constraint in the context of the pose, but it's better to keep the original pose intact
746  //so let's do a full copy
747  core::pose::Pose helper_pose = pose;
748 
749  //only set the constraints, so we don't lose time scoring other stuff
754 
755 
756 
757  bool first_pass = true;
758  Size best_constraint(0);
759  core::Real cur_low_e(0.0);
760 
761  for( Size cur_cst(1); cur_cst <= candidate_csts.size(); cur_cst++ ){
762 
764  cur_cstset->add_constraint( candidate_csts[cur_cst] );
765  helper_pose.constraint_set( cur_cstset );
766  helper_scofx( helper_pose );
767 
769 
770  if( first_pass || ( total_cst_e < cur_low_e ) ) {
771  best_constraint = cur_cst;
772  cur_low_e = total_cst_e;
773  }
774  first_pass = false;
775  }
776 
777  return best_constraint;
778 } //determine best constraint function
779 
780 
781 bool
783 {
784  utility::vector1< EnzCstTemplateResCacheOP > const & template_res_cache(
785  protocols::toolbox::match_enzdes_util::get_enzdes_observer( pose )->cst_cache()->param_cache( cst_block_ )->template_res_cache_ );
786 
787  for( core::Size i = 1; i <= template_res_cache.size(); ++i ){
788  if( template_res_cache[i]->not_in_pose() )return true;
789  }
790  return false;
791 }
792 
793 /*
794 utility::vector1< core::conformation::ResidueCOP >
795 EnzConstraintParameters::inverse_rotamers_for_residue_missing_in_pose(
796  core::pose::Pose const & pose ) const
797 {
798 
799  EnzCstTemplateResCOP missing_template( this->get_missing_template_res( pose ) );
800 
801  for( core::Size restype_index = 1; restype_index <= missing_template->allowed_res_types().size(); ++restype_index ){
802  core::chemical::ResidueTypeCOP restype( restype_set_->name( missing_template->allowed_res_types()[ restype_index ] ) );
803  utility::vector1< core::conformation::ResidueCOP > raw_rotamers;
804  // for now we'll only work with one rotamer
805  raw_rotamers.push_back( new core::conformation::Residue( restype, true ) );
806 
807 
808  } //loop over all allowed restypes of missing_template
809 }
810 */
811 
812 bool
814  core::pose::Pose & pose
815 ) const
816 {
817 
818  using namespace core::pose;
819 
820  core::pose::PDBInfo & pdbinfo( *(pose.pdb_info() ) );
821  Remarks & rems(pose.pdb_info()->remarks() );
822  EnzdesCstParamCacheOP param_cache( protocols::toolbox::match_enzdes_util::get_enzdes_observer( pose )->cst_cache()->param_cache( cst_block_ ) );
823 
824  for( std::vector< core::pose::RemarkInfo >::iterator remark_it = rems.begin(); remark_it != rems.end(); remark_it++) {
825 
826  bool remark_changed(false);
827  std::string chainA(""), chainB(""), resA(""), resB("");
828  core::Size cst_block(0), exgeom_id( 0 );
829  int rem_pdbposA(0), rem_pdbposB(0);
830 
831  if( !split_up_remark_line( remark_it->value, chainA, resA, rem_pdbposA, chainB, resB, rem_pdbposB, cst_block, exgeom_id ) ) continue;
832 
833  if( cst_block != cst_block_ ) continue;
834 
835  if( (param_cache->template_res_cache_[1]->seqpos_map_size() > 1 ) || (param_cache->template_res_cache_[2]->seqpos_map_size() > 1 ) ){
836  tr << "Error in updating remarks for cst block " << cst_block_ << ". More than one seqpos in template resA or resB." << std::endl;
837  return false;
838  }
839 
840  core::Size seqposA( param_cache->template_res_cache_[1]->seqpos_map_begin()->first );
841  core::Size seqposB( param_cache->template_res_cache_[2]->seqpos_map_begin()->first );
842 
843  if( rem_pdbposA != pdbinfo.number( seqposA ) ){
844  //stupid backwards compatibility: if a ligand is present as resA and pdbpos is 0,
845  //leave untouched for now
846  if( (rem_pdbposA != 0 ) || !pose.residue( seqposA ).is_ligand() ){
847  remark_changed = true;
848  rem_pdbposA = pdbinfo.number( seqposA );
849  }
850  }
851  if( chainA[0] != pdbinfo.chain( seqposA ) ){
852  remark_changed = true;
853  chainA = pdbinfo.chain( seqposA );
854  }
855  if( resA != pose.residue( seqposA ).name3() ){
856  remark_changed = true;
857  resA = pose.residue( seqposA ).name3();
858  }
859 
860  if( rem_pdbposB != pdbinfo.number( seqposB) ){
861  remark_changed = true;
862  rem_pdbposB = pdbinfo.number( seqposB );
863  }
864  if( chainB[0] != pdbinfo.chain( seqposB ) ){
865  remark_changed = true;
866  chainB = pdbinfo.chain( seqposB );
867  }
868  if( resB != pose.residue( seqposB ).name3() ){
869  remark_changed = true;
870  resB = pose.residue( seqposB ).name3();
871  }
872 
873  if( remark_changed ){
874  remark_it->value = assemble_remark_line( chainA, resA, rem_pdbposA, chainB, resB, rem_pdbposB, cst_block, exgeom_id );
875  }
876  }
877  return true;
878 }
879 
880 
883 {
884  return resA_;
885 }
886 
889 {
890  return resB_;
891 }
892 
893 
896 {
897  return resA_;
898 }
899 
900 
903 {
904  return resB_;
905 }
906 
907 
910 {
911 
912  utility::vector1< EnzCstTemplateResCacheOP > const & template_res_cache =
913  protocols::toolbox::match_enzdes_util::get_enzdes_observer( pose )->cst_cache()->param_cache( cst_block_ )->template_res_cache_;
914 
915  if( template_res_cache.size() != 2 ) utility_exit_with_message( "More or less than 2 template res caches detected in enzdes cst param cache");
916  if( template_res_cache[1]->not_in_pose() && template_res_cache[2]->not_in_pose() ) utility_exit_with_message("Error: Both template residues are missing in the pose. This shouldn't happen...\n");
917 
918  if( template_res_cache[1]->not_in_pose() ) return resA_;
919  else if( template_res_cache[2]->not_in_pose() ) return resB_;
920  else{
921  utility_exit_with_message("Error: no template residue is missing in the pose, this shouldn't have happened... \n");
922  }
923  //unreachable
924  return NULL;
925 }
926 
929 {
930  utility::vector1< EnzCstTemplateResCacheOP > const & template_res_cache =
931  protocols::toolbox::match_enzdes_util::get_enzdes_observer( pose )->cst_cache()->param_cache( cst_block_ )->template_res_cache_;
932 
933  if( template_res_cache.size() != 2 ) utility_exit_with_message( "More or less than 2 template res caches detected in enzdes cst param cache");
934  if( template_res_cache[1]->not_in_pose() && template_res_cache[2]->not_in_pose() ) utility_exit_with_message("Error: Both template residues are missing in the pose. This shouldn't happen...\n");
935 
936  if( template_res_cache[1]->not_in_pose() ) return resB_;
937  else if( template_res_cache[2]->not_in_pose() ) return resA_;
938  else{
939  utility_exit_with_message("Error: no template residue is missing in the pose, this shouldn't have happened... \n");
940  }
941 
942  //unreachable
943  return NULL;
944 }
945 
946 
947 std::set< std::string >
949  core::pose::Pose const & pose,
950  core::Size seqpos ) const
951 {
952 
953  EnzCstTemplateResCOP template_res;
954  EnzdesCstParamCacheCOP param_cache( protocols::toolbox::match_enzdes_util::get_enzdes_observer( pose )->cst_cache()->param_cache( cst_block_ ) );
955 
956  std::set< std::string > to_return;
957 
958  if( param_cache->template_res_cache(1)->contains_position( seqpos ) ) template_res = resA_;
959  else if( param_cache->template_res_cache(2)->contains_position( seqpos ) ) template_res = resB_;
960 
961  else return to_return;
962 
963  for( core::Size i = 1; i <= template_res->allowed_res_types().size(); ++i ){
964  to_return.insert( template_res->allowed_res_types()[i] );
965  }
966 
967  return to_return;
968 }
969 
970 void
972 {
973  resA_->set_external_position( pos );
974 }
975 
976 
977 void
979 {
980  resB_->set_external_position( pos );
981 }
982 
983 
984 void
986 
987  EnzdesCstParamCacheOP param_cache( protocols::toolbox::match_enzdes_util::get_enzdes_observer( pose )->cst_cache()->param_cache( cst_block_ ) );
988  for( utility::vector1< CovalentConnectionReplaceInfoCOP >::iterator cov_it = param_cache->covalent_connections_.begin();
989  cov_it != param_cache->covalent_connections_.end(); ++cov_it ){
990  (*cov_it)->remove_covalent_connection_from_pose( pose );
991  }
992  param_cache->covalent_connections_.clear();
993 }
994 
995 void
997 {
998  resA_->remap_resid( smap );
999  resB_->remap_resid( smap );
1000 }
1001 
1002 }
1003 } //enzdes
1004 } //protocols
1005 
1006