Rosetta 3.5
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
EnzCstTemplateRes.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 Constraints
11 /// @brief
12 /// @author Florian Richter, floric@u.washington.edu
13 
14 // Unit headers
16 
17 //package headers
22 
23 // Project headers
25 #include <core/chemical/AA.hh> //needed to convert one letter AA codes
26 #include <core/chemical/ResidueTypeSet.hh> //have to include complete file
27 #include <core/pose/Pose.hh>
28 // AUTO-REMOVED #include <core/scoring/Energies.hh>
29 #include <core/id/AtomID.hh>
30 #include <basic/options/option.hh>
32 
33 
34 // Utility Headers
35 // AUTO-REMOVED #include <utility/io/izstream.hh>
36 #include <utility/string_util.hh>
37 #include <iostream>
38 // AUTO-REMOVED #include <fstream>
39 #include <string>
40 #include <sstream>
41 
42 #include <basic/Tracer.hh>
43 
44 
45 // option key includes
46 
47 #include <basic/options/keys/enzdes.OptionKeys.gen.hh>
48 
50 #include <utility/vector1.hh>
51 
52 
53 
54 static basic::Tracer tr("protocols.toolbox.match_enzdes_util.EnzCstTemplateRes");
55 
56 namespace protocols {
57 namespace toolbox {
58 namespace match_enzdes_util {
59 
60 /// @details Auto-generated virtual destructor
62 
63 /// @details Auto-generated virtual destructor
65 
66 
67 void
69 {
70  remap_atomid_vector( smap, atom1_ );
71  remap_atomid_vector( smap, atom2_ );
72  remap_atomid_vector( smap, atom3_ );
73 }
74 
75 void
77  core::id::SequenceMapping const & smap,
78  std::vector< core::id::AtomID > & atomid_vec
79 )
80 {
81  for( std::vector< core::id::AtomID >::iterator vec_it = atomid_vec.begin();
82  vec_it != atomid_vec.end(); ++vec_it ){
83 
84  core::Size newpos = smap[ vec_it->rsd() ];
85  if( newpos == 0 ) utility_exit_with_message("A catalytic residue is apparently missing from the pose");
86 
87  *vec_it = core::id::AtomID( vec_it->atomno(), newpos );
88  }
89 }
90 
91 
92 
94  core::chemical::ResidueTypeSetCAP src_restype_set
95 ) : rb_minimizable_(true), is_backbone_(false),
96  identical_tag_found_(false), corresponding_res_block_(0),
97  corresponding_res_num_in_block_(0),
98  restype_set_(src_restype_set), enz_io_param_( NULL )
99 {
100  clear_all();
101 }
102 
103 
105  core::chemical::ResidueTypeSetCAP src_restype_set,
106  EnzConstraintParametersCAP src_enzio_param )
107 :
108  rb_minimizable_(true), is_backbone_(false),
109  identical_tag_found_(false), corresponding_res_block_(0),
110  corresponding_res_num_in_block_(0),
111  restype_set_(src_restype_set), enz_io_param_( src_enzio_param)
112 {
113  clear_all();
114 }
115 
116 
117 /// @brief WARNING: currently doesn't copy the template atoms in the respos map
119  EnzCstTemplateResCOP other,
120  EnzConstraintParametersCAP new_ref_param)
121 :
122  //respos_map_(other->respos_map_), //old, remove
123  atom1_(other->atom1_),
124  atom2_(other->atom2_),
125  atom3_(other->atom3_),
126  at1_type_(other->at1_type_),
127  at2_type_(other->at2_type_),
128  at3_type_(other->at3_type_),
129  allowed_res_types_(other->allowed_res_types_),
130  atom_inds_for_restype_( other->atom_inds_for_restype_),
131  rb_minimizable_( other->rb_minimizable_ ),
132  is_backbone_( other->is_backbone_ ),
133  respos_from_external_(other->respos_from_external_),
134  identical_tag_found_(other->identical_tag_found_),
135  corresponding_res_block_(other->corresponding_res_block_),
136  corresponding_res_num_in_block_(other->corresponding_res_num_in_block_),
137  restype_set_(other->restype_set_),
138  enz_io_param_(new_ref_param),
139  param_index_(other->param_index_)
140 {
141 }
142 
143 /// @brief read and set up the general information for one residue of one pair block in a cstfile
144 void
145 EnzCstTemplateRes::read_params(std::istringstream & line_stream)
146 {
147  using namespace core::chemical;
148 
149  rb_minimizable_ = true; //true by default
150 
151  //input from cst file
152  std::string tag = "";
153  std::string allowed_1res_raw;
154  std::vector< std::string > allowed_3res_raw;
155  std::string buffer = "";
156  core::Size size_buffer(0);
157 
158 
159  line_stream >> tag;
160  //tr.Info << "template_res.read tag is: " << tag << " ";
161  if ( tag == "atom_name:") {
162  std::string a1, a2, a3;
163  line_stream >> a1 >> a2 >> a3 ;
164  atom1_.push_back(a1);
165  atom2_.push_back(a2);
166  atom3_.push_back(a3);
167  // else if (tag == "atom_name") line_stream >> skip(1) >> bite(4, parameters->res1_at1name_) >> skip(1);
168  } else if (tag == "atom_type:") {
169  line_stream >> at1_type_ >> at2_type_ >> at3_type_;
170  } else if (tag == "residue1:") {
171  line_stream >> allowed_1res_raw;
172  } else if (tag == "residue3:") {
173  while(!line_stream.fail()) { line_stream >> buffer; allowed_3res_raw.push_back(buffer);}
174  } else if (tag == "identical:") {
176  identical_tag_found_ = true;
177  } else if (tag == "seqpos:"){
178  while( !line_stream.fail() ){
179  line_stream >> size_buffer;
180  respos_from_external_.push_back( size_buffer );
181  }
182  }
183 
184  else if ( tag == "no_rb_min" ) rb_minimizable_ = false;
185  else if ( tag == "is_backbone" ) is_backbone_ = true;
186 
187  else{
188  std::cerr << "Line in cstfile specifying template residue with tag " << tag << " was not recognized and will be ignored. " << std::endl;
189  }
190 
191  //done reading parameters, now the processing starts:
192  //1. make sure the ResidueTypeSet knows about the residues specified in the input file
193  //2. if atom types have been put in, make sure they only have 4 letters.
194  //3. if this is an identical line, make sure that the two residues declared identical
195  // have the same allowed res types
196 
197  //first process 3-letter code input
198  for (std::vector< std::string >::iterator it = allowed_3res_raw.begin(); it != allowed_3res_raw.end(); ++it) {
199  if( it->size() == 2 ) *it = " " + *it;
200  if( restype_set_->has_name3( *it ) ) {
201  allowed_res_types_.push_back( *it );
202  }
203  else{
204  utility_exit_with_message("Error in cstfile: Residue with 3-letter code "+*it+" is unknown.");
205  }
206  }
207  //and now do the same for 1-letter code input (only canonical aas will work)
208  for(Size ii = 0; ii != allowed_1res_raw.size(); ii++){
209 
210  if( oneletter_code_specifies_aa( allowed_1res_raw[ii] ) ){
211 
212  std::string cur_res_name3 = name_from_aa( aa_from_oneletter_code( allowed_1res_raw[ii] ) );
213  if( restype_set_->has_name3( cur_res_name3 ) ) allowed_res_types_.push_back( cur_res_name3 );
214  else{
215  utility_exit_with_message("Unexpected error in program: Residue "+cur_res_name3+" is unknown. ResidueTypeSet setup seems to not have worked properly.");
216  }
217  }
218  else{
219  //std::string fock( (char*) &allowed_1res_raw[ii] );
220  std::string fock( 1,allowed_1res_raw[ii] );
221  utility_exit_with_message("Error in cstfile: Residue with one letter code "+ fock +" is unknown.");
222  }
223  }
224 
225  //make sure atom names are capped to four characters
226  if(at1_type_ != ""){at1_type_ = at1_type_.substr(0,4);}
227  if(at2_type_ != ""){at2_type_ = at2_type_.substr(0,4);}
228  if(at3_type_ != ""){at3_type_ = at3_type_.substr(0,4);}
229 
230 } //EnzCstTemplateRes::read_params
231 
232 
233 
234 /// @brief show the contents of a particular instance
236 {
237  using namespace core::chemical;
238 
239  tr.Info << "Parameters read for template residue: atom ids are :";
240  for(core::Size i = 1; i <= atom1_.size(); ++i) tr.Info << " (" << atom1_[i] << " " << atom2_[i] << " " << atom3_[i] << ")";
241  tr.Info << ", first atom name is " << at1_type_ <<" and allowed residues are: ";
242  for (utility::vector1< std::string >::const_iterator res_it = allowed_res_types_.begin(); res_it != allowed_res_types_.end(); ++res_it) {
243  tr.Info << *res_it << ", ";
244  }
245  tr.Info << std::endl ;
246 }
247 
248 
249 
250 /// @brief check whether the data gathered from the cst file and the pdbfile/pose is consistent in itself and with one another
252 
253  using namespace core::chemical;
254  EnzCstTemplateResCacheOP template_cache( protocols::toolbox::match_enzdes_util::get_enzdes_observer( pose )->cst_cache()->param_cache( enz_io_param_->cst_block() )->template_res_cache( param_index_ ) );
255 
256  //first check whether we actually have a residue to process new
257  if(template_cache->seqpos_map_.size() == 0){
258  std::cerr << "Error: no residues for this template." << std::endl;
259  utility::exit( EXIT_FAILURE, __FILE__, __LINE__);
260  }
261 
262 
263  //then we check if this acutally needs to be done (cause if it's done twice we get fucked up behaviour)
264  if( template_cache->pose_data_uptodate_ == true ) return;
265 
266  //then check whether residues specified in the pdbfile were in the list specified in the cstfile,
267  //and for each residue, check whether the atoms specified in the cst file actually match atoms in this residue type
268  for (std::map< Size, EnzCstTemplateResAtomsOP >::iterator respos_it = template_cache->seqpos_map_.begin(); respos_it != template_cache->seqpos_map_.end(); ++respos_it){
269 
270  ResidueTypeCOP cur_res = & pose.residue_type( respos_it->first );
271  std::string cur_res_name3 = pose.residue( respos_it->first ).name3();
272  //utility::trim( cur_res_name3 );
273 
274  //tr.Info << "resis in pose " << pose.residue( respos_it->first ).name3() << " " << respos_it->first <<";";
275 
276  if( std::find( allowed_res_types_.begin(), allowed_res_types_.end(), cur_res_name3 ) == allowed_res_types_.end() ){
277  std::cerr << "Error: residue " << pose.residue( respos_it->first).name3() << respos_it->first << "found in pdb header is not allowed by data in cstfile." << std::endl;
278  std::cerr << "Allowed restypes:";
279  for ( utility::vector1< std::string >::const_iterator iter = allowed_res_types_.begin(); iter != allowed_res_types_.end(); ++iter ) {
280  std::cerr << " " << *iter;
281  }
282  std::cerr << std::endl;
283  utility::exit( EXIT_FAILURE, __FILE__, __LINE__);
284  }
285 
286  //now assign the atoms based on the cst file input, input of atom name takes priority over input of atom type
287  std::map< core::chemical::ResidueTypeCOP, utility::vector1< utility::vector1< core::Size > > >::iterator res_aid_it = atom_inds_for_restype_.find( cur_res );
288 
289  if( res_aid_it == atom_inds_for_restype_.end() ){
290  this->determine_atom_inds_for_restype( cur_res );
291  res_aid_it = atom_inds_for_restype_.find( cur_res );
292  }
293 
294  for( core::Size at1_ct = 1; at1_ct <= res_aid_it->second[1].size(); ++at1_ct ){
295  core::id::AtomID at1id( res_aid_it->second[1][at1_ct], respos_it->first);
296  respos_it->second->atom1_.push_back( at1id );
297  //tr << "for pose residue " << respos_it->first << " atom1, pushed back id " << res_aid_it->second[1][at1_ct] << std::endl;
298  }
299 
300  for( core::Size at2_ct = 1; at2_ct <= res_aid_it->second[2].size(); ++at2_ct ){
301  core::id::AtomID at2id( res_aid_it->second[2][at2_ct], respos_it->first);
302  respos_it->second->atom2_.push_back( at2id );
303 
304  //tr << "for pose residue " << respos_it->first << " atom2, pushed back id " << res_aid_it->second[2][at2_ct] << std::endl;
305  }
306 
307  for( core::Size at3_ct = 1; at3_ct <= res_aid_it->second[3].size(); ++at3_ct ){
308  core::id::AtomID at3id( res_aid_it->second[3][at3_ct], respos_it->first);
309  respos_it->second->atom3_.push_back( at3id );
310  //tr << "for pose residue " << respos_it->first << " atom3, pushed back id " << res_aid_it->second[3][at3_ct] << std::endl;
311  }
312 
313  } //loop over all residue positions in the pose
314 
315  template_cache->pose_data_uptodate_ = true;
316 } //get pose data function
317 
318 
319 
322 {
323 
324  EnzCstTemplateResCacheCOP template_cache( protocols::toolbox::match_enzdes_util::get_enzdes_observer( pose )->cst_cache()->param_cache( enz_io_param_->cst_block() )->template_res_cache( param_index_ ) );
325 
326  std::map< Size, EnzCstTemplateResAtomsOP >::const_iterator at_it = template_cache->seqpos_map_.find( seqpos );
327 
328  if( at_it == template_cache->seqpos_map_.end() ){
329  utility_exit_with_message("Error: could not find template atoms in EnzCstTemplateRes.\n");
330  }
331 
332  return at_it->second;;
333 }
334 
335 bool
337 {
338  EnzCstTemplateResCacheOP template_cache( protocols::toolbox::match_enzdes_util::get_enzdes_observer( pose )->cst_cache()->param_cache( enz_io_param_->cst_block() )->template_res_cache( param_index_ ) );
339  //there are three strategies to find a residue that wasn't mentioned in the PDB REMARKs
340  //1. if it was given externally, i.e. through a 'seqpos' entry in the cst file or
341  // through being speficially set through the accessor function
342  //
343  //2. if this residue is set to corresponding/identical to another residue in the cstfile
344  //
345  //3. if there is only a single residue in the pose that is in the allowed residue types
346  // of this TemplateRes. This may sound somewhat arbitrary, but in most enzyme design cases
347  // where there is only one ligand this will yield that ligand
348 
349  if( template_cache->seqpos_map_.size() != 0 ){
350  utility_exit_with_message("Error: function find_in_pose_... was called even though there is stuff in the respos_map.\n");
351  }
352 
353  //first option 1
354  if( respos_from_external_.size() != 0 ){
356  ex_it != respos_from_external_.end(); ++ex_it ){
357  template_cache->add_position_in_pose( *ex_it );
358  }
359  template_cache->not_in_pose_ = false;
360  //not_in_pose_ = false;
361  return true;
362  }
363 
364  //then option 2
366 
367  EnzCstTemplateResCOP corresponding_res;
369  corresponding_res = enz_io_param_->enz_io()->enz_cst_params( corresponding_res_block_ )->resA();
370  }
371  else{
372  corresponding_res = enz_io_param_->enz_io()->enz_cst_params( corresponding_res_block_ )->resB();
373  }
374  EnzCstTemplateResCacheCOP corresponding_res_cache( protocols::toolbox::match_enzdes_util::get_enzdes_observer( pose )->cst_cache()->param_cache( corresponding_res->enz_io_param_->cst_block() )->template_res_cache( corresponding_res->param_index_ ) );
375 
376  //found the right template residue, now get the positions in the pose where it is
377  for( std::map< Size, EnzCstTemplateResAtomsOP >::const_iterator pos_it = corresponding_res_cache->seqpos_map_begin();
378  pos_it != corresponding_res_cache->seqpos_map_end(); ++pos_it ){
379  template_cache->add_position_in_pose( pos_it->first );
380  }
381 
382  if( template_cache->seqpos_map_.size() == 0 ) return false;
383  else {
384  template_cache->not_in_pose_ = false;
385  return true;
386  }
387  }
388 
389  //then option 3
390  utility::vector1< core::Size > found_positions;
391  for( Size i = 1; i <= pose.total_residue(); ++i){
392  std::string cur_res_name3 = pose.residue( i ).name3();
393  utility::vector1< std::string >::iterator resfind = find( allowed_res_types_.begin(), allowed_res_types_.end(), cur_res_name3);
394 
395  if( resfind != allowed_res_types_.end() ) found_positions.push_back( i );
396  }
397  if( found_positions.size() == 1){
398  template_cache->add_position_in_pose( found_positions[1] );
399  tr << "Found residue " << pose.residue( found_positions[1] ).name3() << " for CstBlock " << enz_io_param_->cst_block() << " without REMARK line in pose at position " << found_positions[1] << "." << std::endl;
400  template_cache->not_in_pose_ = false;
401  return true;
402  }
403 
404  return false;
405 
406 } //find_in_pose_if_missing_from_header
407 
408 
409 
410 void
412 
413  atom1_.clear(); atom2_.clear(); atom3_.clear();
414  at1_type_ = ""; at2_type_ = ""; at3_type_ = "";
415  allowed_res_types_.clear();
418  respos_from_external_.clear();
419  atom_inds_for_restype_.clear();
420  param_index_ = 0;
421 }
422 
423 void
425  respos_from_external_.clear();
426  respos_from_external_.push_back( resnum );
427 }
428 
429 
430 void
432 {
433  for( core::Size i = 1; i <= respos_from_external_.size(); ++i ){
434 
435  core::Size newpos = smap[ respos_from_external_[i] ];
436  if( newpos == 0 ) utility_exit_with_message("A catalytic residue is apparently missing from the pose");
437 
438  respos_from_external_[i] = newpos;
439  }
440 }
441 
442 void
444  core::chemical::ResidueTypeCOP restype ) const
445 {
446 
447  Size natoms = restype->natoms();
448 
449  utility::vector1< core::Size > at1_ids, at2_ids, at3_ids;
450 
451  if( !atom1_.empty() ){
452  for(core::Size i = 1; i <= atom1_.size(); ++i) {
453 
454  at1_ids.push_back( restype->atom_index(atom1_[i]) );
455 
456  if( atom2_[i] != "" ){
457  at2_ids.push_back( restype->atom_index(atom2_[i]) );
458  }
459 
460  if( atom3_[i] != "" ){
461  at3_ids.push_back( restype->atom_index(atom3_[i]) );
462  }
463  }
464  }
465 
466  else if ( at1_type_ != ""){
467 
468  // we need to know the atom indices based on the atom_type_name.
469  // there is no function in the ResidueType class to do this yet, so we have to
470  //do the following hacky implementation for now
471 
472  for(Size ii = 1; ii <= natoms; ii++){
473  core::chemical::AtomType at1type = restype->atom_type( ii );
474 
475  if(at1type.name() == at1_type_) {
476  if(basic::options::option[basic::options::OptionKeys::enzdes::enz_debug] ) {
477  tr.Info << "Adding atom " << ii << " with name " << at1type.name() << " for restype " << restype->name() << " to atom1 vector." << std::endl;
478  }
479 
480  at1_ids.push_back( ii );
481  //core::id::AtomID temp_at1id(ii,respos_it->first);
482  //respos_it->second->atom1_.push_back( temp_at1id );
483  }
484  }
485 
486  if(at1_ids.size() == 0 ) {
487  std::cerr << "Error: ResidueType " << restype->name() << " does not have an atom of type " << at1_type_ << std::endl;
488  utility::exit( EXIT_FAILURE, __FILE__, __LINE__);
489  }
490 
491 
492  //now we have to find the base atoms for each possible atoms for atom1
493  for (utility::vector1< core::Size >::iterator at_it = at1_ids.begin(); at_it != at1_ids.end(); ++at_it){
494 
495  Size id_firstbase = restype->atom_base( *at_it );
496  Size id_secondbase = restype->atom_base( id_firstbase );
497 
498  //ATTENTION: BACKBONE CONSTRAINT SPECIAL CASE: if an nbb or a CA atom are constrained
499  //the secondbase will be identical to the first atom, i.e. this torsion will be undefined
500  //to circumvent this, we set the id_secondbase to 3, the C atom
501  if( ( *at_it == 1) && ( id_firstbase == 2 ) && (id_secondbase == 1 ) ) id_secondbase = 3;
502  else if( ( *at_it == 2) && ( id_firstbase == 1) && (id_secondbase == 2 ) ) id_secondbase = 3;
503 
504  //ATTENTION: HISTIDINE SPECIAL CASE: if the first atom happens to be the ND1, we set the second base
505  //to be the CD2. this ensures that torsion B is identical for ND1 and NE2, so only one cst file needed
506  if( restype->name3() == "HIS" && restype->atom_name( *at_it ) == " ND1"){
507  id_secondbase = restype->atom_index( " CD2");
508  }
509 
510  at2_ids.push_back( id_firstbase );
511  at3_ids.push_back( id_secondbase );
512 
513  //core::id::AtomID temp_at2id( id_firstbase , respos_it->first );
514  //core::id::AtomID temp_at3id( id_secondbase , respos_it->first );
515  //respos_it->second->atom2_.push_back( temp_at2id );
516  //respos_it->second->atom3_.push_back( temp_at3id );
517  }
518  }
519  else{
520  std::cerr << "Error: cstfile did not specify any atoms for Residue " << restype->name3() << "." << std::endl;
521  utility::exit( EXIT_FAILURE, __FILE__, __LINE__);
522  }
523 
524 
526  at_ids.push_back( at1_ids );
527  at_ids.push_back( at2_ids );
528  at_ids.push_back( at3_ids );
529 
531 
532 
533 } //determine_atom_ids_for_restype
534 
535 
536 
539  core::Size template_atom,
540  core::chemical::ResidueTypeCOP restype ) const
541 {
542 
543  //utility::vector1< std::string > const & atom_names;
544  //std::string const & atom_type;
545 
546 
547  // this might change in the future
548  if( template_atom == 1 ){
549  //atom_names = atom1_;
550  //atom_type = at1_type_;
551  }
552 
553  else if( template_atom == 2 ){
554  //atom_names = atom2_;
555  //atom_type = at2_type_;
556  }
557 
558  else if( template_atom == 3 ){
559  //atom_names = atom3_;
560  //atom_type = at3_type_;
561  }
562 
563  else utility_exit_with_message("When trying to find template_atom atom_ids for restype, illegal parameter was passed in for the template_atom. this has to be either 1,2, or 3" );
564 
565  RestypeToTemplateAtomsMap::const_iterator res_it = atom_inds_for_restype_.find( restype );
566  if( res_it == atom_inds_for_restype_.end() ){
567  this->determine_atom_inds_for_restype( restype );
568  res_it = atom_inds_for_restype_.find( restype );
569  }
570  utility::vector1< utility::vector1< core::Size > > const & template_atoms = res_it->second;
571  return template_atoms[ template_atom ];
572 
573 }
574 
575 bool
577  core::conformation::Residue const & res1,
578  core::conformation::Residue const & res2
579 ) const {
580  core::Real const sqdist_cutoff(0.2*0.2); //hardcoded for now
581 
582  RestypeToTemplateAtomsMap::const_iterator res1_it(atom_inds_for_restype_.find( &(res1.type()) ) ), res2_it(atom_inds_for_restype_.find( &(res2.type()) ) );
583  if( res1_it == atom_inds_for_restype_.end() ) utility_exit_with_message("Residue of type "+res1.type().name()+" is not part of EnzCstTemplateRes.");
584  if( res2_it == atom_inds_for_restype_.end() ) utility_exit_with_message("Residue of type "+res2.type().name()+" is not part of EnzCstTemplateRes.");
585 
586  utility::vector1< utility::vector1< core::Size > > const & res1_at_ids( res1_it->second );
587  utility::vector1< utility::vector1< core::Size > > const & res2_at_ids( res2_it->second );
588  //tr << "beginning redundancy check, there are " << res1_at_ids[1].size() << " atom definitions for res1." << std::endl;
589  //first redundancy check: if there are different numbers of
590  //atom1s, the residues are non-redundant
591  if( res1_at_ids[1].size() != res2_at_ids[1].size() ) return false;
592 
593  for( core::Size i = 1; i <= res1_at_ids[1].size(); ++i){
594  //find the closest set from res2
595  core::Real smallest_large_deviation_this_set( sqdist_cutoff + 1.0 );
596 
597  //tr << "ATOM1 res1 atom " << res1.atom_name( res1_at_ids[1][i] ) << " has sqdist of " << closest_atom1_sqdist << " from res2 atom " << res2.atom_name( res2_at_ids[1][1] ) << std::endl;
598 
599  for( core::Size j = 1; j <= res2_at_ids[1].size(); ++j ){
600  core::Real large_deviation_this_pair( res1.atom( res1_at_ids[1][i] ).xyz().distance_squared( res2.atom( res2_at_ids[1][j] ).xyz() ) );
601 
602  core::Real atom2_deviation( res1.atom( res1_at_ids[2][i] ).xyz().distance_squared( res2.atom( res2_at_ids[2][j] ).xyz() ) );
603  if( atom2_deviation > large_deviation_this_pair ) large_deviation_this_pair = atom2_deviation;
604 
605  core::Real atom3_deviation( res1.atom( res1_at_ids[3][i] ).xyz().distance_squared( res2.atom( res2_at_ids[3][j] ).xyz() ) );
606 
607  if( atom3_deviation > large_deviation_this_pair ) large_deviation_this_pair = atom3_deviation;
608 
609  if( large_deviation_this_pair < smallest_large_deviation_this_set ) smallest_large_deviation_this_set = large_deviation_this_pair;
610  //tr << "res 1 set" <<i << " and res 2 set" << j << " have large_deviation of " << large_deviation_this_pair << std::endl;
611  }
612  if( smallest_large_deviation_this_set > sqdist_cutoff ) return false;
613 
614  } //loop over the different template atom sets
615 
616  //if we make it to here, that means no atoms were
617  //farther apart than the cutoff
618  return true;
619 }
620 
621 void
623 {
624 
625  if( !identical_tag_found_ ) return;
626 
627  //first some safety checks
629  || ( enz_io_param_->cst_block() == corresponding_res_block_ ) ) {
630 
631  utility_exit_with_message("Cstfile has wrong format: 'identical' tag for Cstblock "+utility::to_string( enz_io_param_->cst_block() ) + " not formatted properly.\n");
632  }
633 
634  if( enz_io_param_->cst_block() < corresponding_res_block_) {
635  utility_exit_with_message("Cstfile has wrong format: 'identical' tag for Cstblock "+utility::to_string( enz_io_param_->cst_block() ) + " is referring to a block of higher number. Please rewrite Cstfile such that identity tags only refer to blocks of higher numbers.\n");
636  }
637 
638  EnzConstraintParametersCOP corresponding_pair = enz_io_param_->enz_io()->enz_cst_params( corresponding_res_block_);
639 
640  utility::vector1< std::string > residue_names_to_match;
641 
642  if( corresponding_res_num_in_block_ == 1 ) residue_names_to_match = corresponding_pair->resA()->allowed_res_types();
643  else residue_names_to_match = corresponding_pair->resB()->allowed_res_types();
644 
645  for( utility::vector1< std::string >::const_iterator restype_it = allowed_res_types_.begin(); restype_it != allowed_res_types_.end(); ++restype_it ){
646  utility::vector1< std::string >::const_iterator resfind = find(residue_names_to_match.begin(), residue_names_to_match.end(), *restype_it );
647 
648  if( resfind == residue_names_to_match.end() ){
649  utility_exit_with_message("Error in cstfile 'identical' tag for Cstblock "+utility::to_string( enz_io_param_->cst_block() ) + " Allowed residue types for this cst block is not identical to the allowed residue types for the other cst_block.\n");
650  }
651  }
652 }
653 
654 }
655 }//enzdes
656 }//protocols