Rosetta 3.5
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
ResidueType.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 ResidueType.cc
11 ///
12 /// @brief
13 /// A class for defining a type of residue
14 ///
15 /// @details
16 /// This class contains the "chemical" information for residues. This does not contain the actual xyz coordinates of a
17 /// particular residue in a specific peptide. (xyz coordinates are found in core/conformation/Residue.hh). A residue
18 /// in Rosetta can be a ligand, DNA, amino acid, or basically anything. A residue is read in through residue_io.cc and
19 /// read from parameter files, generally located in the database chemical/residue_types. For ligands, or anything that
20 /// is not one of the natural 20 AAs, a parameter has to be provided to rosetta through the -extra_res_fa flag.
21 /// residue_io.cc sets private member data in ResidueType. The primary data that are set are: atoms, mmatoms,
22 /// orbitals, and properties of the particular residue type. These properties can be modified through patches, which
23 /// is controlled through PatchOperations.cc. If the residue_type of a residue is modified, the indices of atoms and
24 /// mmatoms and everything associated with those indices must be redefined. This reordering of indices is taken care
25 /// of with the function reorder_primary_data().
26 ///
27 /// Setting of primary data and then reordering is important. Primary data for the following are described:
28 ///
29 /// Atoms: Setting of atoms includes indexing the atoms into vectors, saving their names into vectors/maps, saving the
30 /// associated mm_atom_type into a vector, saving bond connections into vectors, etc, etc. Since everything is
31 /// allocated into vectors, it is easy to reorder those vectors. On any given residue, the heavy atoms are put into
32 /// the vector first, (their indices are first,) and hydrogens are put in last.
33 ///
34 /// Properties: Properties of a residue include things like DNA, PROTEIN, SC_ORBITALS, CHARGED, etc. These properties
35 /// indicate the type of residue it is and what properties are associated with the residue. They are set when read in.
36 /// Several lines of code must be modified to get them to work, all found here in ResidueType.cc.
37 ///
38 /// Orbitals: Orbitals are indexed separately from atoms. They function much the same way as atoms, except for some
39 /// key differences. To find atoms bonded to orbitals, you must provide the atom index, not the orbital index. (I
40 /// haven't figured out how to get the reverse to work because of the separate indices.) Orbital xyz coordinates are
41 /// not updated when atom coordinates are. This is to keep speed consistent with just having atoms. To output the
42 /// orbitals, use the flag -output_orbitals.
43 ///
44 /// @author
45 /// Phil Bradley
46 /// Steven Combs - these comments
47 ////////////////////////////////////////////////////////////////////////
48 
49 // Unit headers
52 
53 // Package Headers
55 
56 // Project Headers
58 // AUTO-REMOVED #include <core/chemical/ResidueTypeSet.hh>
64 
65 #include <numeric/xyz.functions.hh>
66 #include <numeric/NumericTraits.hh>
67 
68 //#include <core/scoring/ScoringManager.hh>
69 
70 // ObjexxFCL headers
71 #include <ObjexxFCL/FArray2D.hh>
72 // AUTO-REMOVED #include <ObjexxFCL/format.hh>
73 #include <ObjexxFCL/string.functions.hh>
74 
75 // Utility headers
76 // AUTO-REMOVED #include <utility/io/ozstream.hh>
77 // AUTO-REMOVED #include <utility/io/izstream.hh>
78 #include <basic/Tracer.hh>
79 #include <utility/PyAssert.hh>
80 
81 // Options and Option key includes (needed for protonated versions of the residues - pH mode)
82 #include <basic/options/option.hh>
83 // AUTO-REMOVED #include <basic/options/keys/run.OptionKeys.gen.hh>
84 #include <basic/options/keys/pH.OptionKeys.gen.hh>
85 
87 #include <core/chemical/Element.hh>
90 #include <utility/vector1.hh>
91 
92 //Auto using namespaces
93 namespace ObjexxFCL { namespace fmt { } } using namespace ObjexxFCL::fmt; // AUTO USING NS
94 //Auto using namespaces end
95 
96 namespace core {
97 namespace chemical {
98 
99 using namespace ObjexxFCL;
100 using namespace ObjexxFCL::fmt;
101 
102 static basic::Tracer tr("core.chemical.ResidueType");
103 
104 /// must be a better place for this, probably already exists!
105 inline
108 {
109  std::string trimmed_name( name );
110  left_justify( trimmed_name ); trim( trimmed_name ); // simpler way to dothis?
111  return trimmed_name;
112 }
113 
114 ResidueType::ResidueType(
115  AtomTypeSetCAP atom_types,
116  ElementSetCAP elements,
117  MMAtomTypeSetCAP mm_atom_types,
118  orbitals::OrbitalTypeSetCAP orbital_types//, CSDAtomTypeSetCAP csd_atom_types kwk commenting out csd atom types until they are fully functional
119 ) :
120  atom_types_( atom_types ),
121  elements_( elements ),
122  mm_atom_types_( mm_atom_types ),
123  orbital_types_( orbital_types),
124 // csd_atom_types_( csd_atom_types ),
125  residue_type_set_( 0 ),
126  natoms_(0),
127  nheavyatoms_(0),
128  n_hbond_acceptors_(0),
129  n_hbond_donors_(0),
130  n_orbitals_(0),
131  n_backbone_heavyatoms_(0),
132  first_sidechain_hydrogen_( 0 ),
133  ndihe_( 0 ),
134  //lower_connect_atom_( 0 ),
135  //upper_connect_atom_( 0 ),
136  // silly that we have to initialize these to false
137  // seems to be necessary, at least in gcc debug build inside gdb...
138  rotamer_library_name_( "" ),
139  use_ncaa_rotlib_( false ),
140  ncaa_rotlib_n_rots_( 0 ),
141  is_polymer_( false ),
142  is_protein_( false ),
143  is_charged_( false ),
144  is_polar_( false ),
145  has_sc_orbitals_(false),
146  is_aromatic_( false ),
147  is_DNA_( false ),
148  is_RNA_( false ),
149  is_NA_( false ),
150  is_carbohydrate_( false ),
151  is_ligand_( false ),
152  is_surface_( false ),
153  is_terminus_( false ),
154  is_lower_terminus_( false ),
155  is_upper_terminus_( false ),
156  is_acetylated_nterminus_( false ),
157  is_methylated_cterminus_( false ),
158  is_coarse_( false ), //currently for coarse_RNA only
159  is_adduct_( false ),
160  aa_( aa_unk ),
161  rotamer_aa_( aa_unk ),
162  name1_(),
163  nbr_atom_(1),
164  nbr_radius_( 0 ),
165  force_nbr_atom_orient_(false),
166  molecular_mass_(0),
167  molar_mass_(0),
168  n_actcoord_atoms_( 0 ),
169  lower_connect_id_( 0 ),
170  upper_connect_id_( 0 ),
171  n_non_polymeric_residue_connections_( 0 ),
172  n_polymeric_residue_connections_( 0 ),
173  carbohydrate_info_(NULL),
174  finalized_(false),
175  nondefault_(false),
176  base_restype_name_(""),
177  serialized_(false)
178 {}
179 
181 {
182  tr.Trace << "Residue dstor" << std::endl;
183 }
184 
185 ///
186 ResidueTypeSet const &
188 {
189  if ( residue_type_set_ == 0 ) {
190  utility_exit_with_message( "ResidueType::residue_type_set: pointer is not set!");
191  }
192  return *residue_type_set_;
193 }
194 
195 
196 //////////////////////////////////////////////////////////////////////////////
197 
198 /// make a copy
201 {
202  ResidueTypeOP rsd_ptr( new ResidueType( *this ) );
203  return rsd_ptr;
204 }
205 
206 ///
207 void
209 {
210  residue_type_set_ = set_in;
211 }
212 
213 Atom & ResidueType::atom(Size const atom_index){
214  return atoms_[atom_index];
215 }
216 Atom const & ResidueType::atom(Size const atom_index) const{
217  return atoms_[atom_index];
218 }
219 Atom & ResidueType::atom(std::string const & atom_name){
220  return atoms_[ atom_index(atom_name) ];
221 }
222 Atom const & ResidueType::atom(std::string const & atom_name) const{
223  return atoms_[ atom_index(atom_name) ];
224 }
225 Orbital const & ResidueType::orbital(Size const orbital_index) const{
226  return orbitals_[orbital_index];
227 }
228 Orbital const & ResidueType::orbital(std::string const & orbital_name) const{
229  return orbitals_[ orbital_index(orbital_name) ];
230 }
231 
232 
233 
234 /// @details set the atom which connects to the lower connection
235 void
237 {
238  finalized_ = false;
239  if ( atm_name == "NONE" ) {
240  if ( lower_connect_id_ != 0 ) {
241  tr.Debug << "ERASING LOWER_CONNECT: " << lower_connect_id_ << " lcid: " << upper_connect_id_ << std::endl;
243  to_erase += lower_connect_id_ - 1;
244  residue_connections_.erase( to_erase );
246  assert( n_polymeric_residue_connections_ != 0 );
249  lower_connect_id_ = 0;
250 
251  }
252  } else {
253  if ( lower_connect_id_ == 0 ) {
254  ResidueConnection rc( atom_index( atm_name ) );
255  residue_connections_.push_back( rc );
258  } else {
259  residue_connections_[ lower_connect_id_ ].atomno( atom_index( atm_name ) );
260  }
261  }
263 }
264 
265 /// set the atom which connects to the upper connection
266 void
268 {
269 
270  finalized_ = false;
271  if ( atm_name == "NONE" ) {
272  if ( upper_connect_id_ != 0 ) {
273  tr.Debug << "ERASING UPPER_CONNECT: " << upper_connect_id_ << " lcid: " << lower_connect_id_ << std::endl;
275  to_erase += upper_connect_id_ - 1;
276  residue_connections_.erase( to_erase );
277  assert( n_polymeric_residue_connections_ != 0 );
280  upper_connect_id_ = 0;
281  }
282  } else {
283  if ( upper_connect_id_ == 0 ) {
284  ResidueConnection rc( atom_index( atm_name ) );
285  residue_connections_.push_back( rc );
288  } else {
289  residue_connections_[ upper_connect_id_ ].atomno( atom_index( atm_name ) );
290  }
291  }
293 }
294 
295 ResidueConnection const &
297 {
298  //return upper_connect_;
299  assert( is_polymer_ );
300  assert( upper_connect_id_ != 0 );
302 }
303 
304 ///
305 ResidueConnection const &
307 {
308  assert( is_polymer_ );
309  assert( lower_connect_id_ != 0 );
311  //return lower_connect_;
312 }
313 
314 Size
316  assert( is_polymer_ );
317  assert( lower_connect_id_ != 0 );
318  return residue_connections_[ lower_connect_id_ ].atomno();
319 }
320 
321 /// @brief index number of the atom which connects to the upper connection
322 Size
324 {
325  assert( is_polymer_ );
326  assert( upper_connect_id_ != 0 );
327  return residue_connections_[ upper_connect_id_ ].atomno();
328 }
329 
330 /// @brief number of ResidueConnections, counting polymeric residue connections
331 Size
333 {
334  return residue_connections_.size();
335 }
336 
337 Size
339  return residue_connections_[ resconn_id ].atomno();
340 }
341 
342 
343 /// @brief get a ResidueConection
344 ResidueConnection const &
346 {
347  return residue_connections_[i];
348 }
349 
352 {
353  return residue_connections_[ i ];
354 }
355 
356 ///////////////////////////////////////////////////////////////////////////////
357 //
358 
359 /// @brief Get the chemical atom_type for this atom by it index number in this residue
360 ///
361 /// @details If we want the atom_type index (integer), we get this from
362 /// the conformation::Atom itself, as seen in the code below
363 AtomType const &
364 ResidueType::atom_type( Size const atomno ) const
365 {
366  PyAssert((atomno > 0) && (atomno <= atoms_.size()), "ResidueType::atom_type( Size const atomno ): atomno is not in this ResidueType!");
367  return ( *atom_types_ )[ atoms_[ atomno ].atom_type_index() ];
368 }
369 
370 /// @brief Get the atom name by index
371 std::string const &
372 ResidueType::atom_name( Size const index ) const
373 {
374  PyAssert((index > 0) && (index <= atoms_.size()), "ResidueType::atom_name( Size const index ): index is not in this ResidueType!");
375  return atoms_[ index ].name();
376 }
377 
378 /// @brief get index of an atom's base atom
379 Size
380 ResidueType::atom_base( Size const atomno ) const
381 {
382  PyAssert((atomno > 0) && (atomno <= atom_base_.size()), "ResidueType::atom_base( Size const atomno ): atomno is not in this ResidueType!");
383  return atom_base_[ atomno ];
384 }
385 
386 /// @brief get index of an atom's second base atom
387 Size
388 ResidueType::abase2( Size const atomno ) const
389 {
390  PyAssert((atomno > 0) && (atomno <= abase2_.size()), "ResidueType::abase2( Size const atomno ): atomno is not in this ResidueType!");
391  return abase2_[ atomno ];
392 }
393 
394 
395 /// @note this does not set xyz coordinates for the added atom
396 void
398  std::string const & atom_name,
399  std::string const & atom_type_name,
400  std::string const & mm_atom_type_name,
401  Real const charge
402 )
403 {
404  // signal that we need to update the derived data
405  finalized_ = false;
406 
407  // increment atom count
408  ++natoms_;
409  // index lookup by name
411  atom_index_[ strip_whitespace( atom_name ) ] = natoms_;
412 
413  // store the atom types
414  // the next calls will fail if the atom type name is unrecognized
415  Size const type( atom_types_->atom_type_index( atom_type_name ) );
416  Size const mm_type( mm_atom_types_->atom_type_index( mm_atom_type_name ) );
417 
418  // store the name
419  atoms_.push_back( Atom(
420  atom_name,
421  mm_atom_type_name,
422  type, mm_type,
423  charge,
424  Vector(0.0),
425  AtomICoor( 0.0, 0.0, 0.0, atom_name, atom_name, atom_name, *this )
426  ));
427 
428  assert( atoms_.size() == natoms_ );
429 
430  if ( (*atom_types_)[type].is_acceptor() )
432  if ( (*atom_types_)[type].is_donor() )
433  ++n_hbond_donors_;
434 
435  // add the atomic weight of this atom
436  if( elements_ ) { // Be robust if elements_ isn't defined.
437  std::string const & element_name= (*atom_types_)[type].element();
438  int const element_index = elements_->element_index(element_name);
439  molecular_mass_ += (*elements_)[element_index].mass();
440  molar_mass_ += (*elements_)[element_index].weight();
441  } else {
442  tr.Warning << "WARNING Elements set undefined." << std::endl;
443  }
444 
445  parents_.push_back(0);
446 
447  // allocate space for the new atom !!!!!!!!!!!!!!!!!!!!!!1
448  // eg, in the atom/resconn map
449  assert( atom_2_residue_connection_map_.size() == natoms_-1 &&
450  bonded_neighbor_.size() == natoms_-1 &&
451  atom_base_.size() == natoms_-1);
453  bonded_neighbor_.resize( natoms_ ); // added here to handle residues w/ no bonds
455  cut_bond_neighbor_.resize( natoms_ ); // added here to handle residues w/ no bonds
456  atom_base_.push_back( natoms_ ); // default value, should generally be changed
457 
459 
460 }
461 
462 /// @brief set atom type
463 void
465  std::string const & atom_name,
466  std::string const & atom_type_name
467 )
468 {
469  atoms_[ atom_index( atom_name ) ].atom_type_index( atom_types_->atom_type_index( atom_type_name ) );
470 }
471 
472 
473 /// @brief set mm atom type
474 void
476  std::string const & atom_name,
477  std::string const & mm_atom_type_name
478 )
479 {
480  atoms_[ atom_index( atom_name ) ].mm_atom_type_index( mm_atom_types_->atom_type_index( mm_atom_type_name ) );
481 }
482 
483 /// @brief Get the MM atom_type for this atom by its index number in this residue
484 MMAtomType const &
485 ResidueType::mm_atom_type( Size const atomno ) const
486 {
487  return ( *mm_atom_types_ )[ atoms_[ atomno ].mm_atom_type_index() ];
488 }
489 
490 orbitals::OrbitalType const &
491 ResidueType::orbital_type(int const orbital_index)const
492 {
493  return ( *orbital_types_ )[ orbitals_[ orbital_index ].orbital_type_index() ];
494 
495 }
496 
497 //core::Size
498 //ResidueType::orbital_type_index(Size const orb_index) const
499 //{
500 // return orbitals_[orb_index].orbital_type_index();
501 //}
502 
503 /// @note this does not set xyz coordiates for the added orbital but sets the index of the orbital and maps
504 /// it to the type of orbital.
505 void
507  std::string & orbital_name,
508  std::string & orbital_type_name
509 )
510 {
511  // signal that we need to update the derived data
512  finalized_ = false;
513 
514  // increment orbital count
515  ++n_orbitals_;
516 
517  // store the atom type
518  // the next call will fail if the orbital type name is unrecognized
519  Size type( orbital_types_->orbital_type_index( orbital_type_name ) );
520 
521  // store the name
522  orbitals_.push_back(Orbital(orbital_name, type, Vector(0.0)));
523  assert( orbitals_.size() == n_orbitals_ );
524 
525  orbitals_index_[ orbital_name ] = n_orbitals_;
526  orbitals_index_[ strip_whitespace( orbital_name ) ] = n_orbitals_;
527 
528  //parents_.push_back(0);
529 
530  // index lookup by name
531 
532 
533 /* // allocate space for the new atom !!!!!!!!!!!!!!!!!!!!!!1
534  // eg, in the atom/resconn map
535  assert( atom_2_residue_connection_map_.size() == natoms_-1 &&
536  bonded_neighbor_.size() == natoms_-1 &&
537  atom_base_.size() == natoms_-1 &&
538  icoor_.size() == natoms_-1 );
539 
540  atom_2_residue_connection_map_.resize( natoms_ );*/
541 
542  //this is a fix so that the psuedo_bonded_neighbor is the correct size. Otherwise, the size
543  //of the psuedo bonds is incorrect when you go and add bonds.
544 
545  //orbital_bonded_neighbor_.resize( natoms_ );
546 
547 }
548 
549 ///////////////////////////////////////////////////////////////////////////////
550 
551 /// @details add a bond between atom1 and atom2 and add a BondType object referencing the bond (default bond type of SingleBond)
552 /** update bonded_neighbor_ and resize it as necessary **/
553 void
555  std::string const & atom_name1,
556  std::string const & atom_name2
557 )
558 {
559  // signal that we need to update the derived data
560  finalized_ = false;
561 
562  if ( !has( atom_name1 ) || !has( atom_name2 ) ) {
563  std::string message = "add_bond: atoms " + atom_name1 + " and " + atom_name2 + " dont exist!";
564  utility_exit_with_message( message );
565  }
566 
567  Size const i1( atom_index_[ atom_name1 ] );
568  Size const i2( atom_index_[ atom_name2 ] );
569 
570  if ( bonded_neighbor_.size() < Size( std::max( i1, i2) ) ) {
571  // ensure enough space for nbrs
572  utility_exit_with_message("ResidueType:: shouldnt get here -- resizing in add_atom");
573  //bonded_neighbor_.resize( std::max( i1,i2 ) );
574  } else {
575  // check if bond already exists
576  AtomIndices const & i1_nbrs( bonded_neighbor_[i1] );
577  if ( std::find( i1_nbrs.begin(), i1_nbrs.end(), i2 ) != i1_nbrs.end() ) {
578  utility_exit_with_message( "dont add residue bonds more than once!" );
579  }
580  }
581 
582  bonded_neighbor_[ i1 ].push_back( i2 );
583  bonded_neighbor_[ i2 ].push_back( i1 );
584  bonded_neighbor_type_[i1].push_back(SingleBond);
585  bonded_neighbor_type_[i2].push_back(SingleBond);
586  //bondType_vector_[i1].push_back(BondType(i1,i2,SingleBond));
587 
588 }
589 
590 /// @details add a bond between atom1 and atom2 and add a BondType object referencing the bond using the specified bondName
591 void ResidueType::add_bond(std::string const & atom_name1, std::string const & atom_name2, BondName bondLabel)
592 {
593  // signal that we need to update the derived data
594  finalized_ = false;
595 
596  if ( !has( atom_name1 ) || !has( atom_name2 ) ) {
597  std::string message = "add_bond: atoms " + atom_name1 + " and " + atom_name2 + " dont exist!";
598  utility_exit_with_message( message );
599  }
600 
601  Size const i1( atom_index_[ atom_name1 ] );
602  Size const i2( atom_index_[ atom_name2 ] );
603 
604  if ( bonded_neighbor_.size() < Size( std::max( i1, i2) ) ) {
605  // ensure enough space for nbrs
606  utility_exit_with_message("ResidueType:: shouldnt get here -- resizing in add_atom");
607  //bonded_neighbor_.resize( std::max( i1,i2 ) );
608  } else {
609  // check if bond already exists
610  AtomIndices const & i1_nbrs( bonded_neighbor_[i1] );
611  if ( std::find( i1_nbrs.begin(), i1_nbrs.end(), i2 ) != i1_nbrs.end() ) {
612  utility_exit_with_message( "dont add residue bonds more than once!" );
613  }
614  }
615 
616  bonded_neighbor_[ i1 ].push_back( i2 );
617  bonded_neighbor_[ i2 ].push_back( i1 );
618  bonded_neighbor_type_[i1].push_back(bondLabel);
619  bonded_neighbor_type_[i2].push_back(bondLabel);
620  //bondType_vector_.push_back(BondType(i1,i2,bondLabel));
621 }
622 
623 ///////////////////////////////////////////////////////////////////////////////
624 ///@brief add an orbital bond between an atom and an orbital.
625 ///@note NOTE!!!!! This is indexed based upon atoms, not orbitals. That means that in your params file
626 /// you must have the atom as the first and orbital as the second.
627 void
629  std::string const & atom_name1,
630  std::string const & orbital_name
631 )
632 {
633  // signal that we need to update the derived data
634  finalized_ = false;
635 
636  if ( !has( atom_name1 ) || !has_orbital( orbital_name ) ) {
637  std::string message = "add_bond: atoms " + atom_name1 + " and " + orbital_name + " dont exist!";
638  utility_exit_with_message( message );
639  }
640 
641  //Size const i1( atom_index_[ atom_name1 ] );
642  Size const i2( orbitals_index_[ orbital_name ] );
643 
644  if(atom_index_.find(atom_name1) == atom_index_.end()){
645  utility_exit_with_message("atom_name: " + atom_name1 +" not found. Improper params file!");
646 
647  }
648 
649  Size const i1( atom_index_[ atom_name1 ] );
650 
651  orbital_bonded_neighbor_[i1].push_back(i2);
652 
653 }
654 
656 ResidueType::orbital_icoor_data(Size const orbital_index) const{
657  return orbitals_[orbital_index].icoor();
658 }
659 
660 
662 ResidueType::new_orbital_icoor_data(Size const orbital_index) const{
663  return orbitals_[orbital_index].new_icoor();
664 }
665 
666 
667 /// @details add a cut_bond between atom1 and atom2, which disallows an atom-tree connection,
668 /// though the atoms are really bonded.
669 /** update cut_bond_ and resize it as necessary **/
670 void
672  std::string const & atom_name1,
673  std::string const & atom_name2
674 )
675 {
676  // signal that we need to update the derived data
677  finalized_ = false;
678 
679  if ( !has( atom_name1 ) || !has( atom_name2 ) ) {
680  std::string message = "add_cut_bond: atoms " + atom_name1 + " and " + atom_name2 + " dont exist!";
681  utility_exit_with_message( message );
682  }
683 
684  Size const i1( atom_index_[ atom_name1 ] );
685  Size const i2( atom_index_[ atom_name2 ] );
686 
687  if ( cut_bond_neighbor_.size() < Size( std::max( i1, i2) ) ) {
688  // ensure enough space for nbrs
689  utility_exit_with_message("ResidueType:: shouldnt get here -- resizing in add_atom");
690  //bonded_neighbor_.resize( std::max( i1,i2 ) );
691  } else {
692  // check if bond already exists
693  AtomIndices const & i1_nbrs( cut_bond_neighbor_[i1] );
694  if ( std::find( i1_nbrs.begin(), i1_nbrs.end(), i2 ) != i1_nbrs.end() ) {
695  utility_exit_with_message( "dont add residue bonds more than once!" );
696  }
697  }
698 
699  cut_bond_neighbor_[ i1 ].push_back( i2 );
700  cut_bond_neighbor_[ i2 ].push_back( i1 );
701 }
702 
703 
704 ///////////////////////////////////////////////////////////////////////////////
705 
706 /// add a chi angle defined by four atoms
707 void
709  Size const chino,
710  std::string const & atom_name1,
711  std::string const & atom_name2,
712  std::string const & atom_name3,
713  std::string const & atom_name4
714  )
715 {
716  // signal that we need to update the derived data
717  finalized_ = false;
718 
719  if ( !has( atom_name1 ) || !has( atom_name2 ) ||
720  !has( atom_name3 ) || !has( atom_name4 ) ) {
721  utility_exit_with_message("ResidueType::add_chi: atoms dont exist!" );
722  }
723 
724  AtomIndices atoms;
725  atoms.push_back( atom_index_[ atom_name1 ] );
726  atoms.push_back( atom_index_[ atom_name2 ] );
727  atoms.push_back( atom_index_[ atom_name3 ] );
728  atoms.push_back( atom_index_[ atom_name4 ] );
729  if ( chi_atoms_.size() < chino ) {
730  chi_atoms_.resize( chino );
731  chi_rotamers_.resize( chino );
732  chi_2_proton_chi_.resize( chino );
733  }
734  chi_atoms_[chino] = atoms;
735 
736  is_proton_chi_.push_back( false );
737  chi_2_proton_chi_[ chino ] = 0;
738 } // add_chi
739 
740 
741 /// @details Describe proton behavior for residue type; where should rotamer samples be considered,
742 /// and if expanded rotamers are desired, what deviations from the original rotamer samples
743 /// should be included.
744 /// E.g. dihedral_samples of 60, -60, and 180 could have an extra_sample of
745 /// 20 which would produce rotamers at 40 60 & 80, -40 -60 & -80, and -160, 180 & 160.
746 /// Extra_samples at 10 and 20 would produce 15 different rotamer samples.
747 void
749  Size chino,
750  utility::vector1< Real > dihedral_samples,
751  utility::vector1< Real > extra_samples
752 )
753 {
754  is_proton_chi_[ chino ] = true;
755  proton_chis_.push_back( chino );
756  proton_chi_samples_.push_back( dihedral_samples );
757  proton_chi_extra_samples_.push_back( extra_samples );
758  chi_2_proton_chi_[ chino ] = proton_chis_.size();
759 }
760 
761 ///////////////////////////////////////////////////////////////////////////////
762 
763 /// @details add a rotamer bin for a given chi
764 /** a rotamer bin has the mean and standard deviation**/
765 void
767  Size const chino,
768  Real const mean,
769  Real const sdev
770 )
771 {
772  if ( chi_rotamers_.size() < chino ) chi_rotamers_.resize( chino );
773  chi_rotamers_[chino].push_back( std::make_pair( mean, sdev ) );
774 }
775 
776 
777 ///////////////////////////////////////////////////////////////////////////////
778 
779 /// @details sets atom_base_[atom1] = atom2
780 /** resize atom_base_ vector as necessary **/
781 void
783  std::string const & atom_name1,
784  std::string const & atom_name2
785 )
786 {
787  // signal that we need to update the derived data
788  finalized_ = false;
789 
790  if ( !has( atom_name1 ) || !has( atom_name2 ) ) {
791  utility_exit_with_message( "set_atom_base: atoms dont exist!" );
792  }
793 
794 
795  Size const i1( atom_index_[ atom_name1 ] );
796  Size const i2( atom_index_[ atom_name2 ] );
797 
798  // debug connectivity
799  AtomIndices const & i1_nbrs( bonded_neighbor_[i1] );
800  AtomIndices const & i1_cut_nbrs( cut_bond_neighbor_[i1] );
801 
802  if ( ( std::find( i1_nbrs.begin(), i1_nbrs.end(), i2 ) == i1_nbrs.end() ) &&
803  !( i1 == 1 && i2 == 1 && natoms_ == 1 ) ) { // note we allow special exception for single-atom residue
804  utility_exit_with_message( "set_atom_base: atoms must be bonded!" );
805  }
806  if ( atom_base_.size() < Size(i1) ) utility_exit_with_message("ResidueType:: shouldnt get here!");
807 
808  //Need to add a cut-bond check too!!!
809  if ( std::find( i1_cut_nbrs.begin(), i1_cut_nbrs.end(), i2 ) != i1_cut_nbrs.end() ) {
810  utility_exit_with_message( "set_atom_base: cut_bond disallows specification of atom base!" );
811  }
812 
813  atom_base_[ i1 ] = i2;
814 
815 }
816 
817 ///////////////////////////////////////////////////////////////////////////////
818 
819 /// @details get all specified properties for this residue type
822 {
823  return properties_;
824 }
825 
826 ///////////////////////////////////////////////////////////////////////////////
827 
828 /// @details add a property to this residue
829 /** update boolean property member data accordingly **/
830 void
832 {
833  // signal that we need to update the derived data
834  finalized_ = false;
835 
836  if ( property == "POLYMER" ) {
837  is_polymer_ = true;
838  } else if ( property == "PROTEIN" ) {
839  is_protein_ = true;
840  is_polymer_ = true;
841  } else if ( property == "POLAR" ) {
842  is_polar_ = true;
843  } else if( property == "SC_ORBITALS"){
844  has_sc_orbitals_ = true;
845  } else if ( property == "CHARGED" ) {
846  is_charged_ = true;
847  } else if ( property == "AROMATIC" ) {
848  is_aromatic_ = true;
849  } else if ( property == "COARSE" ) {
850  is_coarse_ = true; //currently only for RNA
851  } else if ( property == "DNA" ) {
852  is_DNA_ = true;
853  is_NA_ = true;
854  is_polymer_ = true;
855  } else if ( property == "RNA" ) {
856  is_RNA_ = true;
857  is_NA_ = true;
858  is_polymer_ = true;
859  } else if ( property == "CARBOHYDRATE") {
860  is_carbohydrate_ = true;
861  } else if ( property == "LIGAND" ) {
862  is_ligand_ = true;
863  } else if ( property == "SURFACE" ) {
864  is_surface_ = true;
865  } else if ( property == "LOWER_TERMINUS" ) {
866  is_terminus_ = true;
867  is_lower_terminus_ = true;
868  } else if ( property == "UPPER_TERMINUS" ) {
869  is_terminus_ = true;
870  is_upper_terminus_ = true;
871  } else if ( property == "PHOSPHONATE" ) {
872  is_polymer_ = true;
873  is_phosphonate_ = true;
874  } else if ( property == "PHOSPHONATE_UPPER" ) {
875  is_terminus_ = true;
876  is_upper_terminus_ = true;
877  is_phosphonate_ = true;
878  is_phosphonate_upper_ = true;
879  } else if ( property == "TERMINUS" ) {
880  is_terminus_ = true;
881  } else if ( property == "ACETYLATED_NTERMINUS" ) {
882  is_terminus_ = true;
883  is_lower_terminus_ = true;
885  } else if ( property == "METHYLATED_CTERMINUS" ) {
886  is_terminus_ = true;
887  is_upper_terminus_ = true;
889  } else if (property == "BRANCH_POINT") {
890  ; // Null statement for now.... ~ Labonte
891  } else if (
892  (property == "ALDOSE") ||
893  (property == "KETOSE") ||
894  (property == "L_SUGAR") ||
895  (property == "D_SUGAR") ||
896  (property == "FURANOSE") ||
897  (property == "PYRANOSE") ||
898  (property == "SEPTANOSE") ||
899  (property == "ALPHA_SUGAR") ||
900  (property == "BETA_SUGAR") ||
901  (property == "URONIC_ACID")) {
902  ; // Null statement -- these properties will be added to carbohydrate_info_ by update_derived_data().
903  } else {
904  tr.Warning << "WARNING:: unrecognized residue type property: " << property << std::endl;
905  }
906 
907  properties_.push_back( property );
908 }
909 
910 ///////////////////////////////////////////////////////////////////////////////
911 
912 /// @details delete a property to this residue
913 /** update boolean property member data accordingly **/
914 // Added by Andy M. Chen in June 2009
915 // This is needed for deleting properties, which occurs in certain PTM's
916 
917 void
919 {
920  // signal that we need to update the derived data
921  finalized_ = false;
922 
923  if ( property == "POLYMER" ) {
924  is_polymer_ = false;
925  } else if ( property == "PROTEIN" ) {
926  is_protein_ = false;
927  } else if ( property == "POLAR" ) {
928  is_polar_ = false;
929  }else if(property == "SC_ORBITALS"){
930  has_sc_orbitals_ = false;
931  }else if ( property == "CHARGED" ) {
932  is_charged_ = false;
933  } else if ( property == "AROMATIC" ) {
934  is_aromatic_ = false;
935  } else if ( property == "COARSE" ) {
936  is_coarse_ = false;
937  } else if ( property == "DNA" ) {
938  is_DNA_ = false;
939  } else if ( property == "RNA" ) {
940  is_RNA_ = false;
941  } else if ( property == "CARBOHYDRATE") {
942  is_carbohydrate_ = false;
943  } else if ( property == "LIGAND" ) {
944  is_ligand_ = false;
945  } else if ( property == "SURFACE" ) {
946  is_surface_ = false;
947  } else if ( property == "LOWER_TERMINUS" ) {
948  // could add an is_lower_terminus_ bool if needed?
949  is_lower_terminus_ = false;
950  } else if ( property == "UPPER_TERMINUS" ) {
951  is_upper_terminus_ = false;
952  } else if ( property == "TERMINUS" ) {
953  is_terminus_ = false;
954  } else if ( property == "PHOSPHONATE" ) {
955  is_phosphonate_ = false;
956  } else if ( property == "PHOSPHONATE_UPPER" ) {
957  is_phosphonate_upper_ = false;
958  } else if ( property == "ACETYLATED_NTERMINUS" ) {
959  is_acetylated_nterminus_ = false;
960  } else if ( property == "METHYLATED_CTERMINUS" ) {
961  is_methylated_cterminus_ = false;
962  } else {
963  tr.Warning << "WARNING:: unrecognized residuetype property: " << property << std::endl;
964  }
965 
966  properties_.push_back( property );
967 }
968 
969 
970 ///////////////////////////////////////////////////////////////////////////////
971 
972 /// @details redefine a chi angle based on four atoms
973 // Added by Andy M. Chen in June 2009
974 // This function is almost an exact copy of the add_chi function except that vector resizing does NOT occur.
975 // It is needed for certain PTM's that affects proton chis (e.g. phosphorylation and sulfation).
976 
977 void
979  Size const chino,
980  std::string const & atom_name1,
981  std::string const & atom_name2,
982  std::string const & atom_name3,
983  std::string const & atom_name4
984  )
985 {
986  // signal that we need to update the derived data
987  finalized_ = false;
988 
989  if ( !has( atom_name1 ) || !has( atom_name2 ) ||
990  !has( atom_name3 ) || !has( atom_name4 ) ) {
991  utility_exit_with_message("ResidueType::redefine_chi: atoms dont exist!" );
992  }
993 
994  AtomIndices atoms;
995  atoms.push_back( atom_index_[ atom_name1 ] );
996  atoms.push_back( atom_index_[ atom_name2 ] );
997  atoms.push_back( atom_index_[ atom_name3 ] );
998  atoms.push_back( atom_index_[ atom_name4 ] );
999  chi_atoms_[chino] = atoms;
1000 
1001  //Assumes that the redifined chi is NOT a proton chi.
1002  // (This is adequate in most cases because PTMs tend to replace hydrogens
1003  // with functional groups rather than the other way around.)
1004  is_proton_chi_[ chino ] = false;
1005  chi_2_proton_chi_[ chino ] = 0;
1006 
1007 
1008 } // redefine_chi
1009 
1010 
1011 
1012 /////////////////////////////////////////////////////////////////
1013 
1014 /// @details add an atom to the list for calculating actcoord center
1015 void
1017 {
1018  assert( is_protein() );
1019  finalized_ = false;
1020  tr.Trace << "adding act coord atom: " << name_ << ' ' << atom << std::endl;
1021  Size atomindex = atom_index( atom );
1022  actcoord_atoms_.push_back( atomindex );
1024 }
1025 
1026 ///////////////////////////////////////////////////////////////////////////////
1027 
1028 ///@details set up atom ordering map old2new, called by finalize()
1029 
1030 /**
1031  because some new heavy atoms are added by patching, some are flagged to be deleted
1032  in delete_atoms_ and some are forced to be backbon atoms as in force_bb_
1033 
1034  old2new[old_atom_index] = new_atom_index
1035 
1036  sets natoms_, nheavyatoms_, and n_backbone_heavyatoms_
1037 
1038  also fills attached_H_begin, attached_H_end
1039 
1040 **/
1041 
1042 void
1044  AtomIndices & old2new
1045 )
1046 {
1047  /////////////////////////////////////////////////////////////////////////////
1048  // reorder!
1049  //
1050  // preserve order of heavyatoms in current list, modulo new backbone heavyatoms that have been added by patching
1051  // these guys need to be moved forward
1052  //
1053  // ** ensure that heavyatoms come before hydrogens
1054  // ** put all hydrogens attached to a heavyatom in a single row
1055  //
1056  // ** adding support for deleting atoms at this stage: calls to delete_atom( name )
1057  // will append to delete_atoms_, must follow with call to finalize()
1058 
1059 
1060  // set atom counts
1061  Size const old_natoms( atoms_.size() );
1062  assert( natoms_ == old_natoms );
1063  natoms_ = old_natoms - delete_atoms_.size();
1064 
1065  // size and initialize the mapping from old to new indices
1066  old2new.clear();
1067  old2new.resize( old_natoms, 0 );
1068 
1069  // process delete_atoms_ to a friendlier form
1070  utility::vector1< bool > keep_me( old_natoms, true );
1071  for ( Size i=1; i<= old_natoms; ++i ) {
1072  if ( std::find( delete_atoms_.begin(), delete_atoms_.end(), i ) != delete_atoms_.end() ) {
1073  tr.Trace << "ResidueType::finalize(): delete atom: " << atoms_[i].name() << std::endl;
1074  keep_me[i] = false;
1075  }
1076  }
1077  delete_atoms_.clear();
1078 
1079  // first fill a list of all the heavyatoms, insisting that backbone come first
1080  AtomIndices old_heavyatom_indices;
1081  for ( Size i=1; i<= old_natoms; ++i ) {
1082  if ( keep_me[ i ] && atom_type( i ).is_heavyatom() &&
1083  ( ( i <= n_backbone_heavyatoms_ ) || // is backbone heavyatom by count from previous call to finalize()
1084  ( std::find( force_bb_.begin(), force_bb_.end(), i ) != force_bb_.end() ) ) ) { // is forced-bb
1085  old_heavyatom_indices.push_back( i );
1086  }
1087  }
1088 
1089  // update the bb-heavy counter:
1090  n_backbone_heavyatoms_ = old_heavyatom_indices.size();
1091  force_bb_.clear();
1092 
1093  // now add sidechain heavyatoms
1094  for ( Size i=1; i<= old_natoms; ++i ) {
1095  if ( keep_me[ i ] && atom_type( i ).is_heavyatom() &&
1096  ( std::find( old_heavyatom_indices.begin(), old_heavyatom_indices.end(), i ) == // not already done
1097  old_heavyatom_indices.end() ) ) {
1098  old_heavyatom_indices.push_back( i );
1099  }
1100  }
1101 
1102  // all the heavyatoms
1103  nheavyatoms_ = old_heavyatom_indices.size();
1104 
1105  // setup old2new, also fill in attached_H_begin/end
1106  attached_H_begin_.clear();
1107  attached_H_end_.clear();
1108  attached_H_begin_.resize( nheavyatoms_, 0 );
1109  attached_H_end_.resize( nheavyatoms_, 0 /*do not change*/);
1110 
1111  Size new_H_index( nheavyatoms_ );
1112  for ( Size new_heavy_index = 1; new_heavy_index <= nheavyatoms_; ++new_heavy_index ) {
1113  Size const old_heavy_index( old_heavyatom_indices[ new_heavy_index ] );
1114 
1115  // mapping between indices
1116  old2new[ old_heavy_index ] = new_heavy_index;
1117 
1118  // now add the attached hydrogens
1119  attached_H_begin_[ new_heavy_index ] = new_H_index + 1;
1120  AtomIndices const & nbrs( bonded_neighbor_[ old_heavy_index ] );
1121  for ( Size j=1; j<= nbrs.size(); ++j ) {
1122  if ( (*atom_types_)[ atoms_[ nbrs[j] ].atom_type_index() ].is_hydrogen()) {
1123  Size const old_H_index( nbrs[j] );
1124  if ( keep_me[ old_H_index ] ) {
1125  ++new_H_index;
1126  old2new[ old_H_index ] = new_H_index;
1127  attached_H_end_[ new_heavy_index ] = new_H_index;
1128  }
1129  }
1130  }
1131  }
1132 }
1133 
1134 
1135 
1136 ///////////////////////////////////////////////////////////////////////////////
1137 
1138 /// reorder primary data in ResidueType given the old2new map, called by finalize()
1139 /**
1140  update the rest private data in ResidueType object after old2new map is set up
1141  by calling setup_atom_ordering (some data have been updated there also)
1142 **/
1143 void
1145  AtomIndices const & old2new
1146 )
1147 {
1148  // now reorder using old2new -- a bit of a nuisance
1149  // there must be a better way to handle this!!!
1150  Size const old_natoms( old2new.size() );
1151  assert( old_natoms == atoms_.size() );
1152 
1153  // copy the old per-atom data: note that attached_H_begin and attached_H_end have already been setup
1154  // and abase2_ is derived data setup down below
1155  utility::vector1< Atom > old_atoms( atoms_ );
1156 
1158  utility::vector1< AtomIndices > old_bonded_neighbor( bonded_neighbor_ );
1160  utility::vector1< AtomIndices > old_cut_bond_neighbor( cut_bond_neighbor_ );
1161  AtomIndices old_atom_base( atom_base_ );
1162 
1163  utility::vector1<Size> old_parents(parents_);
1164 
1165  if ( old_natoms != natoms_ ) { // because we deleted some atoms
1166  atoms_.resize( natoms_ );
1167  //atomic_charge_.resize( natoms_ );
1169  bonded_neighbor_.resize( natoms_ );
1170  bonded_neighbor_type_.resize (natoms_);
1171  cut_bond_neighbor_.resize( natoms_ );
1172  atom_base_.resize( natoms_ );
1173  //icoor_.resize( natoms_ );
1174 
1175  //new_orbital_icoor_id_.resize(natoms_);
1176 
1177  //xyz_.resize( natoms_ );
1178  parents_.resize(natoms_);
1180  }
1181  // fill in the new data
1182  for ( Size old_index=1; old_index<= old_natoms; ++old_index ) {
1183  Size const new_index( old2new[ old_index ] );
1184  if ( new_index == 0 ) continue; // deleted
1185 
1186  atoms_[ new_index ].atom_type_index( old_atoms[ old_index ].atom_type_index() );
1187  atoms_[ new_index ].mm_atom_type_index( old_atoms[ old_index ].mm_atom_type_index() );
1188 // csd_atom_type_index_[ new_index ] = old_csd_atom_type_index[ old_index ];
1189  //atomic_charge_[ new_index ] = old_atomic_charge[ old_index ];
1190  atoms_[ new_index ] = old_atoms[ old_index ];
1191  //atom_name_[ new_index ] = old_atom_name[ old_index ];
1192  //mm_atom_name_[ new_index ] = old_mm_atom_name[ old_index ];
1193 // csd_atom_name_[ new_index ] = old_csd_atom_name[ old_index ];
1194 
1195  atom_base_[ new_index ] = old2new[ old_atom_base[ old_index ] ];
1196  assert( atom_base_[ new_index ] ); // this will fail if we deleted an atom which was the atom_base for another atom
1197 
1198  orbital_bonded_neighbor_[new_index] = old_orbital_bonded_neighbor[old_index];
1199 
1200  bonded_neighbor_[ new_index ].clear();
1201  for ( Size j=1, j_end = old_bonded_neighbor[ old_index ].size(); j<= j_end; ++j )
1202  {
1203  Size const old_nbr( old_bonded_neighbor[ old_index ][j] );
1204  if ( old2new[ old_nbr ] ) bonded_neighbor_[ new_index ].push_back( old2new[ old_nbr ] );
1205  }
1206 
1207 
1208  bonded_neighbor_type_[new_index].clear();
1209  for(Size j=1, j_end=old_bonded_neighbor_type[old_index].size(); j<=j_end; ++j)
1210  {
1211  Size const old_neighbor(old_bonded_neighbor[old_index][j]) ;
1212  if(old2new[old_neighbor] ) bonded_neighbor_type_[new_index].push_back(old_bonded_neighbor_type[old_index][j]);
1213  }
1214 
1215  cut_bond_neighbor_[ new_index ].clear();
1216  for ( Size j=1, j_end = old_cut_bond_neighbor[ old_index ].size(); j<= j_end; ++j )
1217  {
1218  Size const old_nbr( old_cut_bond_neighbor[ old_index ][j] );
1219  if ( old2new[ old_nbr ] ) cut_bond_neighbor_[ new_index ].push_back( old2new[ old_nbr ] );
1220  }
1221 
1222  //xyz_[ new_index ] = old_xyz[ old_index ];
1223  parents_[ new_index ] = old_parents[ old_index ];
1224  // icoor_[ new_index ] = old_icoor[ old_index ];
1225  for ( Size i=1; i<= 3; ++i ) {
1226  ICoorAtomID & stub_atom( atoms_[ new_index ].icoor().stub_atom( i ) );
1227  if ( stub_atom.type() == ICoorAtomID::INTERNAL ) {
1228  stub_atom.atomno( old2new[ stub_atom.atomno() ] );
1229  assert( stub_atom.atomno() ); // this will fail if we deleted a stub atom for some other atom
1230  }
1231  }
1232 
1233  if(orbitals_.size() != 0){
1234  utility::vector1< core::Size > const orbital_indices(orbital_bonded_neighbor_[new_index]);
1235  for (
1237  orbital_index = orbital_indices.begin(),
1238  orbital_index_end = orbital_indices.end();
1239  orbital_index != orbital_index_end; ++orbital_index
1240  )
1241  {
1242 
1243  core::Size stub1( orbitals_[*orbital_index].new_icoor().get_stub1());
1244  core::Size stub2( orbitals_[*orbital_index].new_icoor().get_stub2());
1245  core::Size stub3( orbitals_[*orbital_index].new_icoor().get_stub3() );
1246 
1247  if ( stub1 == 0 || stub2 == 0 || stub3 == 0) {
1248  continue;
1249  }else{
1250  orbitals_[*orbital_index].new_icoor().replace_stub1( old2new[stub1]);
1251  orbitals_[*orbital_index].new_icoor().replace_stub2( old2new[stub2]);
1252  orbitals_[*orbital_index].new_icoor().replace_stub3( old2new[stub3]);
1253  }
1254 
1255 
1256  }
1257 
1258  }
1259 
1260 
1261 
1262  }
1263 
1264  // atom_index_
1265  atom_index_.clear();
1266  for ( Size i=1; i<= natoms_; ++i ) {
1267  atom_index_[ atoms_[i].name() ] = i;
1268  atom_index_[ strip_whitespace( atoms_[i].name() ) ] = i;
1269  }
1270 
1271  // chi_atoms_
1272  for ( Size i=1; i<= chi_atoms_.size(); ++i ) {
1273  for ( Size j=1; j<= 4; ++j ) {
1274  chi_atoms_[i][j] = old2new[ chi_atoms_[i][j] ];
1275  }
1276  }
1277 
1278  // mainchain_atoms_
1279  for ( Size i=1; i<= mainchain_atoms_.size(); ++i ) {
1280  mainchain_atoms_[i] = old2new[ mainchain_atoms_[i] ];
1281  }
1282 
1283  // actcoord_atoms_
1284  assert( n_actcoord_atoms_ == actcoord_atoms_.size() );
1285  for ( Size i=1; i<= actcoord_atoms_.size(); ++i ) {
1286  actcoord_atoms_[i] = old2new[ actcoord_atoms_[i] ];
1287  }
1288 
1289  // nbr_atom_
1290  nbr_atom_ = old2new[ nbr_atom_ ];
1291 
1292  // upper-lower-connect only relevant for polymer
1293  //if ( upper_connect_id_ != 0 ) {
1294  // residue_connections_[ upper_connect_id_ ].atomno( old2new[ residue_connections_[ upper_connect_id_ ].atomno() ] );
1295  //}
1296 
1297  //if ( lower_connect_id_ != 0 ) {
1298  // residue_connections_[ lower_connect_id_ ].atomno( old2new[ residue_connections_[ lower_connect_id_ ].atomno() ] );
1299  //}
1300 
1301  /////////////////////////////////////////////////////////////////////////////
1302  // add additional reordering statements here for new data that you've added
1303  // to ResidueType that's sensitive to atom order
1304 
1305  for ( Size i=1; i<= residue_connections_.size(); ++i ) {
1306  residue_connections_[i].atomno( old2new[ residue_connections_[i].atomno() ] );
1307  AtomICoor new_icoor = residue_connections_[i].icoor();
1308  for ( Size j = 1; j <= 3; ++j ) {
1309  new_icoor.stub_atom( j ).atomno( old2new[ new_icoor.stub_atom( j ).atomno() ] );
1310  }
1311  residue_connections_[ i ].icoor( new_icoor );
1312  assert( residue_connections_[i].atomno() ); //this will fail if we deleted an atom involved in an inter-rsd connection
1313  }
1314 
1316 
1317 
1318 }
1319 
1320 
1321 ///////////////////////////////////////////////////////////////////////////////
1322 
1323 /// @details update derived data in ResidueType, called by finalize()
1324 /**
1325  after primary data have been reordered, update derived data acoordingly,
1326  including\n, Hbond donor and acceptors, path_distance etc.
1327 **/
1328 void
1330 {
1331 
1333  for ( Size i= n_backbone_heavyatoms_ + 1; i<= nheavyatoms_; ++i ) {
1334  if ( attached_H_begin_[i] <= attached_H_end_[i] ) {
1336  break;
1337  }
1338  }
1339 
1340 
1341  // compile atom-index lists of subsets of the atoms
1342  accpt_pos_.clear();
1343  accpt_pos_sc_.clear();
1344  Haro_index_.clear();
1345  Hpol_index_.clear();
1346  atoms_with_orb_index_.clear();
1347  Hpos_polar_.clear();
1348  Hpos_apolar_.clear();
1349  Hpos_polar_sc_.clear();
1350  all_bb_atoms_.clear();
1351  all_sc_atoms_.clear();
1352 
1353 
1354 
1355  for ( Size i=1; i<= natoms_; ++i ) {
1356  AtomType const & type( (*atom_types_)[ atoms_[i].atom_type_index() ] );
1357  //Size const type( atoms_[i].type() );
1358 
1359  //////////////////////////////////
1360  // info derived from the atom_type
1361  // hbond info
1362 /* if(type.is_lone_pair()){
1363  Orbitals_index_.push_back( i );
1364  }*/
1365  //get atoms with orbitals on it
1366  if(type.atom_has_orbital()){
1367  atoms_with_orb_index_.push_back(i);
1368  }
1369 
1370  //get aromatic hydrogens
1371  if(type.is_haro()){
1372  Haro_index_.push_back( i );
1373 
1374  }
1375  //get polar hydrogens
1376  if(type.is_polar_hydrogen()){
1377  Hpol_index_.push_back( i );
1378  }
1379 
1380  if ( type.is_acceptor() ) {
1381  accpt_pos_.push_back( i );
1382  if ( i > n_backbone_heavyatoms_ ) {
1383  accpt_pos_sc_.push_back( i );
1384  }
1385 
1386  }
1387 
1388  if ( type.is_polar_hydrogen() && (std::abs(atoms_[ natoms_ ].charge() ) > 1.0e-3) ) {
1389  Hpos_polar_.push_back( i );
1390  if ( i >= first_sidechain_hydrogen_ ) {
1391  Hpos_polar_sc_.push_back( i );
1392  }
1393  }
1394 
1395  if ( type.is_hydrogen() && ( !type.is_polar_hydrogen() ) ){
1396  Hpos_apolar_.push_back( i );
1397  }
1398 
1399  // Which atoms are backbone and which are sidechain; sometimes nice to just get
1400  // lists instead of iterating over the subranges.
1401  if ( type.is_hydrogen() ) {
1402  if ( i < first_sidechain_hydrogen_ ) {
1403  all_bb_atoms_.push_back( i );
1404  } else {
1405  all_sc_atoms_.push_back( i );
1406  }
1407  } else {
1408  if ( i <= n_backbone_heavyatoms_ ) {
1409  all_bb_atoms_.push_back( i );
1410  } else {
1411  all_sc_atoms_.push_back( i );
1412  }
1413  }
1414 
1415  }
1416 
1417  // donor heavy atoms, acceptor heavy atoms, donor hydrogen atoms setup.
1418  // Must be executed after Hpos_polar_ and accpt_pos_ have been updated.
1421  atom_is_polar_hydrogen_.resize( natoms_ );
1422  std::fill( heavyatom_has_polar_hydrogens_.begin(), heavyatom_has_polar_hydrogens_.end(), 0 );
1423  std::fill( heavyatom_is_an_acceptor_.begin(), heavyatom_is_an_acceptor_.end(), 0 );
1424  std::fill( atom_is_polar_hydrogen_.begin(), atom_is_polar_hydrogen_.end(), 0 );
1425  for ( Size ii = 1; ii <= Hpos_polar_.size(); ++ii ) {
1426  Size hind = Hpos_polar_[ ii ];
1427  atom_is_polar_hydrogen_[ ii ] = 1;
1428  Size base = atom_base_[ hind ];
1429  heavyatom_has_polar_hydrogens_[ base ] = 1;
1430  }
1431  for ( Size ii = 1; ii <= accpt_pos_.size(); ++ii ) {
1433  }
1434 
1435 
1436  // now setup abase2
1437  abase2_.clear();
1438  abase2_.resize( natoms_ );
1439 
1440  for ( Size ii=1, ii_end= accpt_pos_.size(); ii<= ii_end; ++ii ) {
1441  uint const i( accpt_pos_[ii] );
1442  uint const i_base( atom_base_[i] );
1443  assert( i_base != 0 );
1444  AtomIndices const & i_nbrs( bonded_neighbor_[i] );
1445  if ( i_nbrs.size() == 0 ) {
1446  utility_exit_with_message( "failed to set abase2 for acceptor atom, it has no nbrs!" );
1447  } else if ( i_nbrs.size() == 1 ) {
1448  assert( i_nbrs[1] == i_base );
1449  abase2_[ i ] = atom_base_[ i_base ];
1450  //iwd The first child of the root is root's atom_base.
1451  //iwd But if that child has no children, it ends up as its own abase2.
1452  //iwd So instead we use the second child of the parent,
1453  //iwd which must exist if there are 3+ atoms in this tree.
1454  if( abase2_[ i ] == i ) {
1455  AtomIndices const & i_base_nbrs( bonded_neighbor_[i_base] );
1456  for(Size jj = 1, jj_end = i_base_nbrs.size(); jj <= jj_end; ++jj) {
1457  if(i_base_nbrs[ jj ] != i) {
1458  abase2_[ i ] = i_base_nbrs[ jj ];
1459  //TR << "Using " << atom_name(abase2_[ i ]) << " as abase2 for " << atom_name(i) << std::endl;
1460  break;
1461  }
1462  }
1463  }
1464  assert( abase2_[ i ] != i && abase2_[ i ] != i_base && abase2_[ i ] != 0 );
1465  } else if ( i_nbrs[1] == i_base ) {
1466  abase2_[ i ] = i_nbrs[2];
1467  } else {
1468  abase2_[ i ] = i_nbrs[1];
1469  }
1470  }
1471 
1472 
1473  // bond path distances
1474  FArray2D_int path_distances( get_residue_path_distances( *this ));
1475  path_distance_.resize( natoms_ );
1476  for ( Size ii = 1; ii <= natoms_; ++ii ) {
1477  path_distance_[ ii ].resize( natoms_ );
1478  for (Size jj = 1; jj <= natoms_; ++jj ) {
1479  path_distance_[ ii ][ jj ] = path_distances( ii, jj );
1480  }
1481  }
1482 
1483  // get dihedral angles
1484  dihedral_atom_sets_.clear();
1485  dihedrals_for_atom_.resize( natoms_ );
1486  for ( Size ii = 1; ii <= natoms_; ++ii ) dihedrals_for_atom_[ ii ].clear();
1487 
1488  // get for all pairs of atoms seperated by 1 bond
1489  for ( Size central_atom1 = 1; central_atom1 < natoms_; ++central_atom1 ) {
1490  for ( Size central_atom2 = central_atom1+1; central_atom2 <= natoms_; ++central_atom2 ) {
1491  if ( path_distance_[ central_atom1 ][ central_atom2 ] == 1 ) {
1492 
1493  // get all atoms seperated from central_atom1/2 by one bond that are not central_atom2/1
1496 
1497  // ca1
1498  for ( Size i = 1; i <= natoms_; ++i ) {
1499  if ( ( path_distance_[ central_atom1 ][ i ] == 1 ) && ( i != central_atom2 ) ) {
1500  ca1d1.push_back( i );
1501  }
1502  }
1503  // ca2
1504  for ( Size i = 1; i <= natoms_; ++i ) {
1505  if ( ( path_distance_[ central_atom2 ][ i ] == 1 ) && ( i != central_atom1 ) ) {
1506  ca2d1.push_back( i );
1507  }
1508  }
1509 
1510  // for each pair of dihedral angle start or end atoms create a dihedral angle using central atom
1511  for ( utility::vector1< Size >::iterator terminal_atom1 = ca1d1.begin();
1512  terminal_atom1 != ca1d1.end(); ++terminal_atom1 ) {
1513  for ( utility::vector1< Size >::iterator terminal_atom2 = ca2d1.begin();
1514  terminal_atom2 != ca2d1.end(); ++terminal_atom2 ) {
1515  dihedral_atom_set temp( *terminal_atom1, central_atom1, central_atom2, *terminal_atom2 );
1516  dihedral_atom_sets_.push_back( temp );
1517  Size const which_dihedral = dihedral_atom_sets_.size();
1518  dihedrals_for_atom_[ *terminal_atom1 ].push_back( which_dihedral );
1519  dihedrals_for_atom_[ central_atom1 ].push_back( which_dihedral );
1520  dihedrals_for_atom_[ central_atom2 ].push_back( which_dihedral );
1521  dihedrals_for_atom_[ *terminal_atom2 ].push_back( which_dihedral );
1522  }
1523  }
1524 
1525  }
1526  }
1527  }
1528  ndihe_ = dihedral_atom_sets_.size();
1529 
1530 
1531 
1532  // get bond angles
1533  bondangle_atom_sets_.clear();
1534  bondangles_for_atom_.resize( natoms_ );
1535  for ( Size ii = 1; ii <= natoms_; ++ii ) bondangles_for_atom_[ ii ].clear();
1536 
1537  // iterate over all atoms that could be a central atom
1538  for ( Size central_atom = 1; central_atom <= natoms_; ++central_atom ) {
1539 
1540  AtomIndices const & bonded_neighbors( bonded_neighbor_[central_atom] );
1541  Size const num_bonded_neighbors( bonded_neighbors.size() );
1542 
1543  // create all possible combinations of branching atoms
1544  for ( Size i = 1; i < num_bonded_neighbors; ++i ) {
1545  for ( Size j = i+1; j <= num_bonded_neighbors; ++j ) {
1546  bondangle_atom_set temp( bonded_neighbors[i], central_atom, bonded_neighbors[j] );
1547  bondangle_atom_sets_.push_back( temp );
1548  Size const which_angle = bondangle_atom_sets_.size();
1549  bondangles_for_atom_[ bonded_neighbors[i] ].push_back( which_angle );
1550  bondangles_for_atom_[ central_atom ].push_back( which_angle );
1551  bondangles_for_atom_[ bonded_neighbors[j] ].push_back( which_angle );
1552  }
1553  }
1554  }
1555 
1556  // Now for inter-residue connections, find the sets of atoms that are within one and within two bonds
1557  // of a residue connection point. From these sets, all inter-residue bond angle and bond torsions may
1558  // be enumerated when evaluating residue pair energies. Also compute the backwards mapping: a list for
1559  // each atom of the within-1-bond and within-2-bond sets that the atom is listed as being part of. These
1560  // lists are needed when evaluating atom derivatives wrt the bond dihedrals and angles.
1562  for ( Size ii = 1; ii <= residue_connections_.size(); ++ii ) atoms_within_one_bond_of_a_residue_connection_[ ii ].clear();
1563 
1564  within1bonds_sets_for_atom_.resize( natoms_ );
1565  for ( Size ii = 1; ii <= natoms_; ++ii ) within1bonds_sets_for_atom_[ ii ].clear();
1566 
1568  for ( Size ii = 1; ii <= residue_connections_.size(); ++ii ) atoms_within_two_bonds_of_a_residue_connection_[ ii ].clear();
1569 
1570  within2bonds_sets_for_atom_.resize( natoms_ );
1571  for ( Size ii = 1; ii <= natoms_; ++ii ) within2bonds_sets_for_atom_[ ii ].clear();
1572 
1573  for ( Size ii = 1; ii <= residue_connections_.size(); ++ii ) {
1574  Size const ii_resconn_atom = residue_connections_[ ii ].atomno();
1575 
1576  AtomIndices const & ii_bonded_neighbors( bonded_neighbor_[ ii_resconn_atom ] );
1577  Size const ii_num_bonded_neighbors( ii_bonded_neighbors.size() );
1578 
1579  for ( Size jj = 1; jj <= ii_num_bonded_neighbors; ++jj ) {
1580  Size const jj_atom = ii_bonded_neighbors[ jj ];
1581 
1582  // Record that ii_resconn_atom and jj_atom are within a single bond of residue connection ii.
1583  two_atom_set wi1( ii_resconn_atom, jj_atom );
1584  atoms_within_one_bond_of_a_residue_connection_[ ii ].push_back( wi1 );
1585 
1586  // For atoms ii_resconn_atom and jj_atom, mark residue connection ii as a
1587  // connection point the are within one bond of.
1588  Size const which_wi1 = atoms_within_one_bond_of_a_residue_connection_[ ii ].size();
1589  within1bonds_sets_for_atom_[ ii_resconn_atom ].push_back( std::make_pair( ii, which_wi1 ) );
1590  within1bonds_sets_for_atom_[ jj_atom ].push_back( std::make_pair( ii, which_wi1 ));
1591 
1592  AtomIndices const & jj_bonded_neighbors( bonded_neighbor_[ jj_atom ] );
1593  Size const jj_num_bonded_neighbors( jj_bonded_neighbors.size() );
1594 
1595  for ( Size kk = 1; kk <= jj_num_bonded_neighbors; ++kk ) {
1596  Size const kk_atom = jj_bonded_neighbors[ kk ];
1597  if ( kk_atom == ii_resconn_atom ) continue; // skip iiat->jjat->iiat
1598 
1599  three_atom_set wi2( ii_resconn_atom, jj_atom, kk_atom );
1600  atoms_within_two_bonds_of_a_residue_connection_[ ii ].push_back( wi2 );
1601 
1602  Size const which_wi2 = atoms_within_two_bonds_of_a_residue_connection_[ ii ].size();
1603  within2bonds_sets_for_atom_[ ii_resconn_atom ].push_back( std::make_pair( ii, which_wi2 ) );
1604  within2bonds_sets_for_atom_[ jj_atom ].push_back( std::make_pair( ii, which_wi2 ));
1605  within2bonds_sets_for_atom_[ kk_atom ].push_back( std::make_pair( ii, which_wi2 ));
1606  }
1607  }
1608  }
1609 
1610 
1611  if(is_RNA_){ //reinitialize and RNA derived data.
1612  //Reinitialize rna_residuetype_ object! This also make sure rna_residuetype_ didn't inherit anything from the previous update!
1613  //It appears that the rna_residuetype_ is shared across multiple ResidueType object, if the rna_residuetype_ is not reinitialized here!
1614 
1616 
1617  //update_last_controlling_chi is treated seperately for RNA case. Parin Sripakdeevong, June 26, 2011
1619 
1621  } else if (is_carbohydrate_) {
1624  } else {
1626  }
1627 
1628 
1629 // // fill mm_atom_type_index vector
1630 // mm_atom_type_index_.assign( natoms_, 0 );
1631 // for ( int i = 1; i <= natoms_; ++i )
1632 // {
1633 // mm_atom_type_index_[ i ] = mm_atom_types_->atom_type_index( mm_atom_name( i ) );
1634 // }
1635 
1636 }
1637 
1638 
1639 ///////////////////////////////////////////////////////////////////////////////
1640 
1641 /// recalculate derived data, potentially reordering atom-indices
1642 /**
1643  This routine updates all the derived data.\n
1644  Atom order will probably change after this call, so if you add a new
1645  property that depends on atom-indices that will have to be updated below.
1646 **/
1647 /*
1648  data that we have prior to calling this routine:
1649 
1650  name type setting method
1651  ----------------------------------------------------------
1652  atoms_ v1<Atom*> add_atom //from base class
1653  atom_name_ v1<string> add_atom
1654  atom_index_ map<string,int> add_atom
1655  atomic_charge v1<Real> add_atom
1656  bonded_neighbor_ v1<v1<int>> add_bond
1657  bonded_neighbor_type v1<v1<BondName>> add_bond
1658  atom_base_ v1<int> set_atom_base
1659  chi_atoms_ v1<v1<int>> add_chi
1660  properties bools add_property
1661  nbr_atom_ int nbr_atom( int )
1662 
1663  This routine updates all the derived data.
1664 
1665  Atoms_ order will probably change after this call, so if you add a new
1666  property that depends on atom-indices that will have to be updated below.
1667 */
1668 void
1670 {
1671 
1672  AtomIndices old2new;
1673 
1674  setup_atom_ordering( old2new );
1675 
1676  reorder_primary_data( old2new );
1677 
1679 
1680  // debug -- these temporary arrays should have been cleared
1681  assert( force_bb_.empty() && delete_atoms_.empty() );
1682 
1683  // signal that derived data is up to date now
1684  finalized_ = true;
1685 
1686 }
1687 
1688 ////////////////////////////////////////////////////////////////////
1689 
1690 
1691 bool
1693 {
1694 
1695  if ( ! basic::options::option[ basic::options::OptionKeys::pH::pH_mode ].user() ) {
1696  for ( Size ii = 1; ii <= variant_types_.size(); ++ii ) {
1697  if ( ! other.has_variant_type( variant_types_[ ii ] ) ) {
1698  return false;
1699  }
1700  }
1701  return (variant_types_.size() == other.variant_types_.size());
1702  }
1703 
1704  //needed for protonated versions of the residues
1705  else {
1706  int this_variant_count_offset( 0 );
1707  for ( Size ii = 1; ii <= variant_types_.size(); ++ii ) {
1708  if ( variant_types_[ii] == PROTONATED || variant_types_[ii] == DEPROTONATED ) {
1709  this_variant_count_offset = 1;
1710  continue;
1711  }
1712  if ( ! other.has_variant_type( variant_types_[ ii ] ) ) {
1713  return false;
1714  }
1715  }
1716 
1717  int other_variant_count_offset( 0 );
1718  if( other.has_variant_type( PROTONATED ) || other.has_variant_type( DEPROTONATED ) ) {
1719  other_variant_count_offset = 1;
1720  }
1721 
1722  return ( ( variant_types_.size() - this_variant_count_offset ) ==
1723  ( other.variant_types_.size() - other_variant_count_offset ) );
1724  }
1725 }
1726 
1727 bool
1729 {
1730  int this_variant_count_offset( 0 );
1731  for ( Size ii = 1; ii <= variant_types_.size(); ++ii ) {
1732  if ( variant_types_[ii] == ADDUCT ) {
1733  this_variant_count_offset = 1;
1734  continue;
1735  }
1736  if ( ! other.has_variant_type( variant_types_[ ii ] ) ) {
1737  return false;
1738  }
1739  }
1740 
1741  int other_variant_count_offset( 0 );
1742  if( other.has_variant_type( ADDUCT ) ) {
1743  other_variant_count_offset = 1;
1744  }
1745 
1746  return ( ( variant_types_.size() - this_variant_count_offset ) ==
1747  ( other.variant_types_.size() - other_variant_count_offset ) );
1748 }
1749 
1750 
1751 bool
1753 {
1754  std::map< std::string, int >::const_iterator iter
1755  ( atom_index_.find( name ) );
1756  if ( iter == atom_index_.end() ) {
1757  return false;
1758  }
1759  return true;
1760 }
1761 
1762 Size
1764 {
1765 // if ( tr.Debug.visible() ) {
1766 // for ( std::map< std::string, int >::const_iterator iter = atom_index_.begin(); iter != atom_index_.end(); ++iter ) {
1767 // tr.Debug << iter->first << " " << iter->second << std::endl;
1768 // }
1769 // }
1770  std::map< std::string, int >::const_iterator iter
1771  ( atom_index_.find( name ) );
1772  if ( iter == atom_index_.end() ) {
1773 #if defined BOINC
1774  // chu temporary graphic fix for boinc
1775  if ( name == "CA" && !is_protein() ) return 1;
1776 #endif
1777  tr.Error << "atom name : " << name << " not available in residue " << name3() << std::endl;
1778  show_all_atom_names( tr.Error );
1779  tr.Error << std::endl;
1780  utility_exit_with_message("unknown atom_name: " + name3() + " " + name );
1781  }
1782  return iter->second;
1783 }
1784 
1785 core::Size
1787 {
1788 
1789  std::map< std::string, int >::const_iterator iter
1790  ( orbitals_index_.find( name ) );
1791  if ( iter == orbitals_index_.end() ) {
1792  utility_exit_with_message("unknown orbital_name: " + name3() + " " + name );
1793  }
1794  return iter->second;
1795 }
1796 
1797 
1798 
1799 void
1801 {
1802  finalized_ = false;
1803  if ( n_backbone_heavyatoms_ ) {
1804  assert( force_bb_.empty() );
1805  for ( Size i=1; i<= n_backbone_heavyatoms_; ++i ) {
1806  force_bb_.push_back( i );
1807  }
1809  }
1810  force_bb_.push_back( atom_index( name ) );
1811 }
1812 
1813 /// @brief AtomICoord of an atom
1814 AtomICoor const &
1815 ResidueType::icoor( Size const atm ) const
1816 {
1817  return atoms_[ atm ].icoor();
1818 }
1819 
1820 Size
1822 {
1823  finalized_ = false;
1824 
1826  residue_connections_.push_back( ResidueConnection( atom_index( atom_name ) ) );
1828  return residue_connections_.size();
1829 }
1830 
1831 ///@details update actcoord
1832 /** average geometrical center of the set of actcoord_atoms_ */
1833 void
1835 {
1836  rot.actcoord().zero();
1837  if ( n_actcoord_atoms_ > 0 ) {
1838  for ( Size ii = 1; ii <= n_actcoord_atoms_; ++ii )
1839  {
1840  rot.actcoord() += rot.atoms()[ actcoord_atoms_[ ii ]].xyz();
1841  }
1842  rot.actcoord() /= n_actcoord_atoms_;
1843  }
1844 }
1845 
1846 
1847 /// @details set AtomICoor for an atom
1848 ///
1849 /// will update the xyz coords as well if desired, useful inside a patching operation where new
1850 /// atoms are being added.
1851 ///
1852 void
1854  Size const & index,
1855  std::string const & atm,
1856  Real const phi,
1857  Real const theta,
1858  Real const d,
1859  std::string const & stub_atom1,
1860  std::string const & stub_atom2,
1861  std::string const & stub_atom3,
1862  bool const update_xyz // = false
1863 )
1864 {
1865  ICoorAtomID id( atm, *this );
1866  AtomICoor const ic( index, phi, theta, d, stub_atom1, stub_atom2, stub_atom3, *this );
1867 
1868  Size const atomno( id.atomno() );
1869  switch ( id.type() ) {
1870  case ICoorAtomID::INTERNAL:
1871  if ( atoms_.size() < atomno ) utility_exit_with_message("ResidueType:: shouldn't get here!");//icoor_.resize(atomno);
1872  atoms_[ atomno ].icoor( ic );
1873  // update atom_base?
1874  if ( ( stub_atom1 != atm ) && has( stub_atom1 ) &&
1875  ( atom_base_.size() < atomno || atom_base_[ atomno ] == 0 || atom_base_[ atomno ] == atomno ) ) {
1876  set_atom_base( atm, stub_atom1 );
1877  }
1878  if ( update_xyz ) {
1879  set_ideal_xyz( atm, ic.build( *this ) );
1880  //std::cout << "building coords for atm " << name_ << ' ' << atm << ' ' <<
1881  // ic.build(*this)(1) << ' ' <<
1882  // ic.build(*this)(2) << ' ' <<
1883  // ic.build(*this)(3) << std::endl;
1884  }
1885  break;
1886  case ICoorAtomID::CONNECT:
1887  residue_connections_[ atomno ].icoor( ic );
1888  break;
1890  assert( lower_connect_id_ != 0 );
1891  residue_connections_[ lower_connect_id_ ].icoor( ic );
1892  break;
1894  assert( upper_connect_id_ != 0 );
1895  residue_connections_[ upper_connect_id_ ].icoor( ic );
1896  break;
1897  default:
1898  utility_exit_with_message( "unrecognized stub atom id type!" );
1899  }
1900 }
1901 
1902 void
1904  std::string const & atm,
1905  Real const phi,
1906  Real const theta,
1907  Real const d,
1908  std::string const & stub_atom1,
1909  std::string const & stub_atom2,
1910  std::string const & stub_atom3,
1911  bool const update_xyz // = false
1912 )
1913 {
1914  ICoorAtomID id( atm, *this );
1915  AtomICoor const ic( phi, theta, d, stub_atom1, stub_atom2, stub_atom3, *this );
1916 
1917  Size const atomno( id.atomno() );
1918  switch ( id.type() ) {
1919  case ICoorAtomID::INTERNAL:
1920  if ( atoms_.size() < atomno ) utility_exit_with_message("ResidueType:: shoudnt get here!");//icoor_.resize(atomno);
1921  atoms_[ atomno ].icoor( ic );
1922  // update atom_base?
1923  if ( ( stub_atom1 != atm ) && has( stub_atom1 ) &&
1924  ( atom_base_.size() < atomno || atom_base_[ atomno ] == 0 || atom_base_[ atomno ] == atomno ) ) {
1925  set_atom_base( atm, stub_atom1 );
1926  }
1927  if ( update_xyz ) {
1928  set_ideal_xyz( atm, ic.build( *this ) );
1929  //std::cout << "building coords for atm " << name_ << ' ' << atm << ' ' <<
1930  // ic.build(*this)(1) << ' ' <<
1931  // ic.build(*this)(2) << ' ' <<
1932  // ic.build(*this)(3) << std::endl;
1933  }
1934  break;
1935  case ICoorAtomID::CONNECT:
1936  residue_connections_[ atomno ].icoor( ic );
1937  break;
1939  assert( lower_connect_id_ != 0 );
1940  residue_connections_[ lower_connect_id_ ].icoor( ic );
1941  break;
1943  assert( upper_connect_id_ != 0 );
1944  residue_connections_[ upper_connect_id_ ].icoor( ic );
1945  break;
1946  default:
1947  utility_exit_with_message( "unrecognized stub atom id type!" );
1948  }
1949 }
1950 
1951 //set the orbital icoor data.
1952 void
1954  std::string const & orbital,
1955  Real const phi,
1956  Real const theta,
1957  Real const d,
1958  std::string const & stub_atom1,
1959  std::string const & stub_atom2,
1960  std::string const & stub_atom3
1961 )
1962 {
1963  Size orb_indx(orbital_index(orbital));
1964  std::string stub1(stub_atom1);
1965  std::string stub2(stub_atom2);
1966  std::string stub3(stub_atom3);
1967  orbitals::ICoorOrbitalData icoor(phi, theta, d, stub1, stub2, stub3);
1968  orbitals_[ orb_indx ].icoor( icoor );
1969 
1970 
1971  core::Size s1(atom_index_[ stub_atom1 ]);
1972  core::Size s2(atom_index_[ stub_atom2 ]);
1973  core::Size s3(atom_index_[ stub_atom3 ]);
1974  orbitals::ICoorOrbitalData new_icoor(phi, theta, d, s1, s2, s3);
1975 
1976  orbitals_[ orb_indx ].new_icoor( new_icoor );
1977 
1978 
1979 }
1980 
1981 
1983 {
1985 }
1986 
1987 /// @brief A residue parameter file can refer to a set of "pdb rotamers" that can be
1988 /// superimposed onto a starting position for use in the packer. These rotamers
1989 /// are loaded into the pack::dunbrack::RotamerLibrary at the time of their first use.
1991 {
1992  return rotamer_library_name_;
1993 }
1994 
1995 
1997 {
1998  //calculate the geometric center of all atoms in the residue
1999 
2000  Vector total(0.0,0.0,0.0);
2001  for(core::Size index = 1; index <= atoms_.size();++index)
2002  {
2003  total += atoms_[index].ideal_xyz();
2004  }
2005  Vector center = total/atoms_.size();
2006 
2007  //locate the atom which is closest to the center
2008  core::Size min_index = 0;
2009  core::Real min_distance = 50000.0;
2010  for(core::Size index = 1; index <= atoms_.size();++index)
2011  {
2012  core::Real distance = center.distance(atoms_[index].ideal_xyz());
2013  if( (distance < min_distance) && (!atom_is_hydrogen(index)) )
2014  {
2015  min_distance = distance;
2016  min_index = index;
2017  }
2018  }
2019  assert(min_index != 0);
2020  //set neighbor atom
2021  nbr_atom(atoms_[min_index].name());
2022 }
2023 
2025 {
2027  AtomICoor nbr_icoor = icoor(nbr_atom_);
2028  set_icoor(atom_name(nbr_atom_),0.0,0.0,0.0,atom_name(nbr_icoor.stub_atom1().atomno()),
2029  atom_name(nbr_icoor.stub_atom2().atomno()),atom_name(nbr_icoor.stub_atom3().atomno()));
2030 
2031 }
2032 
2034 {
2035  //%TODO: right now i'm ignoring M FRAG lines and M SPLT lines in molfiles
2036  core::Size current_atom_index = atom_index(current_atom);
2037  std::string parent_stub1;
2038  std::string parent_stub2;
2039  std::string parent_stub3;
2040 
2041  //the root atom has dummy stubs and icoords of 0
2042  if(current_atom_index == nbr_atom_)
2043  {
2044  core::Size first_child = bonded_neighbor_[current_atom_index][1];
2045  parent_stub1 = atom_name(current_atom_index);
2046  parent_stub2 = atom_name(first_child);
2047 
2048  if(bonded_neighbor_[first_child].size() > 0)
2049  {
2050  parent_stub3 = atom_name(bonded_neighbor_[first_child][1]);
2051  }else
2052  {
2053  parent_stub3 = atom_name(bonded_neighbor_[current_atom_index][2]);
2054  }
2055  }else
2056  {
2057  core::Size parent_index = parents_[current_atom_index];
2058  AtomICoor parent_icoor = icoor(parent_index);
2059  parent_stub1 = atom_name(current_atom_index);
2060  parent_stub2 = atom_name(parent_index);
2061  parent_stub3 = atom_name(parent_icoor.stub_atom2().atomno());
2062  }
2063 
2064  std::string previous_sibling = parent_stub3;
2065  AtomIndices children = bonded_neighbor_[current_atom_index];
2066  for(core::Size index = 1; index <children.size();++index)
2067  {
2068  core::Size child_index = children[index];
2069 
2070  if((parents_[child_index] != 0) && (child_index != nbr_atom_))
2071  {
2072  continue;
2073  }
2074 
2075  std::string child_stub1 = parent_stub1;
2076  std::string child_stub2 = parent_stub2;
2077  std::string child_stub3 = previous_sibling;
2078  parents_[child_index] = current_atom_index;
2079  if((current_atom_index == nbr_atom_) && (previous_sibling == parent_stub2))
2080  {
2081  child_stub3 = parent_stub3;
2082  }
2083  calculate_icoor(atom_name(child_index),child_stub1,child_stub2,child_stub3);
2084  //set_atom_base(atom_name(child_index),)
2085  assign_internal_coordinates(atom_name(child_index) );
2086  previous_sibling = atom_name(child_index);
2087  }
2088 }
2089 
2091  std::string const & stub_atom1,
2092  std::string const & stub_atom2,
2093  std::string const & stub_atom3)
2094 {
2095  //std::cout <<child << " \""<<stub_atom1 << "\" \""<<stub_atom2<< "\" \""<<stub_atom3 << std::endl;
2096  // This is basically a direct port of calc_internal_coords()
2097  // found in /python/apps/public/molfile_to_params.py
2098  Vector const child_xyz = atom(atom_index(child)).ideal_xyz();
2099  Vector const stub1_xyz = atom(atom_index(stub_atom1)).ideal_xyz();
2100  Vector const stub2_xyz = atom(atom_index(stub_atom2)).ideal_xyz();
2101  Vector const stub3_xyz = atom(atom_index(stub_atom3)).ideal_xyz();
2102 
2103  core::Real distance = child_xyz.distance(stub1_xyz);
2104  core::Real theta = 0.0;
2105  core::Real phi = 0.0;
2106  if(distance <1e-2)
2107  {
2108  tr << "WARNING: extremely small distance=" << distance << " for " <<
2109  child << " ,using 0.0 for theta and phi."<<
2110  " If you were not expecting this warning, something is very wrong" <<std::endl;
2111  }else
2112  {
2113  theta = numeric::angle_radians<core::Real>(child_xyz,stub1_xyz,stub2_xyz);
2114  if( (theta < 1e-2) || (theta > numeric::NumericTraits<Real>::pi()-1e-2) )
2115  {
2116  phi = 0.0;
2117  }else
2118  {
2119  phi = numeric::dihedral_radians<core::Real>(child_xyz,stub1_xyz,stub2_xyz,stub3_xyz);
2120  }
2121 
2122  }
2123  //tr << child << " " << stub_atom1 << " "<< stub_atom2 << " " <<stub_atom3 << " " <<distance << " " << phi << " " << theta <<std::endl;
2124  set_icoor(child,phi,theta,distance,stub_atom1,stub_atom2,stub_atom3);
2125 }
2126 
2127 void
2129  std::string const & atm,
2130  Vector const & xyz_in
2131 )
2132 {
2133  Size const index( atom_index(atm) );
2134  set_ideal_xyz(index,xyz_in);
2135 }
2136 
2137 void
2139  Size index,
2140  Vector const & xyz_in
2141 )
2142 {
2143  if ( index > atoms_.size() ) atoms_.resize(index);
2144  atoms_[index].ideal_xyz( xyz_in );
2145 }
2146 
2147 // Return the CarbohydrateInfo object containing sugar-specific properties for this residue.
2150 {
2151  return carbohydrate_info_;
2152 }
2153 
2154 
2155 /// @details as non-member so it has not to show up in the header
2156 //void
2157 //write_cached_rotlib(
2158 // pack::dunbrack::SingleResidueRotamerLibraryCOP const& rotlib,
2159 // ResidueTypeSetCAP const& res_type_set,
2160 // std::string const& name3
2161 //) {
2162 // std::string dirname = res_type_set->database_directory() + "/dunbrack_cache/";
2163 // std::string filename ( "bbdep_" + name3 );
2164 // tr.Info << "cache dunbrack library for "<<name3 << " in " << dirname+filename << std::endl;
2165 // utility::io::ozstream out( dirname+filename );
2166 // rotlib->write_to_file ( out );
2167 // utility::io::izstream in( dirname+filename );
2168 // if ( !in.good() ) {
2169 // tr.Warning <<"WARNING: can't create cache file in " << dirname << " pls manually" << std::endl;
2170 // tr.Warning <<"WARNING: create subdirectory /dunbrack_cache, with right of writing" << std::endl;
2171 // tr.Warning <<"WARNING: or ask somebody else to put bbdep files there... " << std::endl;
2172 // tr.Warning <<"WARNING: it work's without, but is much slower ! " << std::endl;
2173 // };
2174 //
2175 //}
2176 //
2177 //bool
2178 //read_cached_rotlib(
2179 // pack::dunbrack::SingleResidueRotamerLibraryCOP& rotlib,
2180 // ResidueTypeSetCAP const& res_type_set,
2181 // std::string const& name3
2182 //)
2183 //{
2184 // std::string dirname = res_type_set->database_directory() + "/dunbrack_cache/";
2185 // std::string filename ( "bbdep_" + name3 );
2186 // utility::io::izstream in( dirname+filename );
2187 // if ( in.good() ) {
2188 // rotlib = pack::dunbrack::read_single_dunbrack_library(in, true /*ClassicRotBins*/ );
2189 // return true;
2190 // } else {
2191 // return false;
2192 // }
2193 //}
2194 
2195 ///@details this might return 0, so please check for that
2196 /*pack::dunbrack::SingleResidueRotamerLibraryCAP
2197 ResidueType::get_RotamerLibrary() const
2198 {
2199  //std::cerr << "ResidueType::get_RotamerLibrary() " << name() << "translator: " << (translator_ ? "yes" : "no" ) << " rotlib_ " << (rotlib_ ? "yes" : "no") << std::endl;
2200  // By decree of Andrew and Phil, ResidueType is no longer allowed to own its rotamer library.
2201  // This function exists just to ease the transition.
2202  if ( use_ncaa_rotlib_ ) {
2203  return scoring::ScoringManager::get_instance()->get_NCAARotamerLibrary( *this );
2204  }
2205  return scoring::ScoringManager::get_instance()->get_RotamerLibrary().get_rsd_library(*this);
2206 
2207  //if ( rotlib_ ) {
2208  // return rotlib_;
2209  //}
2210  //// if ( nchi() >= 1 ) {
2211  //if ( bRotamers_ ) { //I favor this approach since it doesn't assume anything
2212  // if ( !read_cached_rotlib( rotlib_, residue_type_set_, name3() ) ) {
2213  // /// APL breaking coarse rotlib
2214  // if ( translator_ ) {
2215  // // rotlib_ = translator_->get_RotamerLibrary();
2216  // // if (rotlib_) write_cached_rotlib( rotlib_, residue_type_set_, name3() );
2217  // }
2218  // else {
2219  // rotlib_ = scoring::ScoringManager::get_instance()->
2220  // get_RotamerLibrary().get_rsd_library(*this);
2221  // }
2222  // }
2223  // bRotamers_ = ( rotlib_ != 0 );
2224  //} else rotlib_ = 0; //nchi == 0
2225  //return rotlib_;
2226 }
2227 
2228 ///@details Manually assign a rotamer library for this residue type,
2229 /// for use in cases where you always want the same set of conformers available.
2230 /// Used for ligands, where conformers are enumerated by external programs ahead of time.
2231 /// Can accept NULL to delete any pre-existing rotamers for this residue type.
2232 void
2233 ResidueType::set_RotamerLibrary(pack::dunbrack::SingleResidueRotamerLibraryCOP rotlib)
2234 {
2235  // By decree of Andrew and Phil, ResidueType is no longer allowed to own its rotamer library.
2236  // This function exists just to ease the transition.
2237  scoring::ScoringManager::get_instance()->get_RotamerLibrary().add_residue_library(*this, rotlib);
2238 }*/
2239 
2240 void
2242 {
2243  tr.Debug << "START DIHEDRAL ANGLES ATOM NAMES" << std::endl;
2244  tr.Debug << "Number of dihe: " << ndihe_ << " " << dihedral_atom_sets_.size() << std::endl;
2245  for ( Size i = 1; i <= ndihe_; ++i )
2246  {
2247 
2248  AtomType at1 = atom_type( dihedral_atom_sets_[ i ].key1() );
2249  AtomType at2 = atom_type( dihedral_atom_sets_[ i ].key2() );
2250  AtomType at3 = atom_type( dihedral_atom_sets_[ i ].key3() );
2251  AtomType at4 = atom_type( dihedral_atom_sets_[ i ].key4() );
2252  MMAtomType at5 = mm_atom_type( dihedral_atom_sets_[ i ].key1() );
2253  MMAtomType at6 = mm_atom_type( dihedral_atom_sets_[ i ].key2() );
2254  MMAtomType at7 = mm_atom_type( dihedral_atom_sets_[ i ].key3() );
2255  MMAtomType at8 = mm_atom_type( dihedral_atom_sets_[ i ].key4() );
2256 
2257  tr.Debug << "PDB:" << "\t"
2258  << atoms_[ dihedral_atom_sets_[ i ].key1() ].name() << "\t"
2259  << atoms_[ dihedral_atom_sets_[ i ].key2() ].name() << "\t"
2260  << atoms_[ dihedral_atom_sets_[ i ].key3() ].name() << "\t"
2261  << atoms_[ dihedral_atom_sets_[ i ].key4() ].name() << "\t"
2262  << "MM:" << "\t"
2263  << atoms_[ dihedral_atom_sets_[ i ].key1() ].mm_name() << "\t"
2264  << atoms_[ dihedral_atom_sets_[ i ].key2() ].mm_name() << "\t"
2265  << atoms_[ dihedral_atom_sets_[ i ].key3() ].mm_name() << "\t"
2266  << atoms_[ dihedral_atom_sets_[ i ].key4() ].mm_name() << "\t"
2267  << "MM2:" << "\t"
2268  << at5.name() << "\t"
2269  << at6.name() << "\t"
2270  << at7.name() << "\t"
2271  << at8.name() << "\t"
2272  << "ROS:" << "\t"
2273  << at1.name() << "\t"
2274  << at2.name() << "\t"
2275  << at3.name() << "\t"
2276  << at4.name() << "\t"
2277  << std::endl;
2278  }
2279  tr.Debug << "END DIHEDRAL ANGLES ATOM NAMES" << std::endl;
2280 }
2281 
2282 void
2284 {
2285  tr.Debug << "START BOND ANGLES ATOM NAMES" << std::endl;
2286  tr.Debug << "Number of bond angles: " << bondangle_atom_sets_.size() << std::endl;
2287  for ( Size i = 1; i <= bondangle_atom_sets_.size(); ++i )
2288  {
2289 
2290  AtomType at1 = atom_type( bondangle_atom_sets_[ i ].key1() );
2291  AtomType at2 = atom_type( bondangle_atom_sets_[ i ].key2() );
2292  AtomType at3 = atom_type( bondangle_atom_sets_[ i ].key3() );
2293  MMAtomType at5 = mm_atom_type( bondangle_atom_sets_[ i ].key1() );
2294  MMAtomType at6 = mm_atom_type( bondangle_atom_sets_[ i ].key2() );
2295  MMAtomType at7 = mm_atom_type( bondangle_atom_sets_[ i ].key3() );
2296 
2297  tr.Debug << "PDB:" << "\t"
2298  << atoms_[ bondangle_atom_sets_[ i ].key1() ].name() << "\t"
2299  << atoms_[ bondangle_atom_sets_[ i ].key2() ].name() << "\t"
2300  << atoms_[ bondangle_atom_sets_[ i ].key3() ].name() << "\t"
2301  << "MM:" << "\t"
2302  << atoms_[ bondangle_atom_sets_[ i ].key1() ].mm_name() << "\t"
2303  << atoms_[ bondangle_atom_sets_[ i ].key2() ].mm_name() << "\t"
2304  << atoms_[ bondangle_atom_sets_[ i ].key3() ].mm_name() << "\t"
2305  << "MM2:" << "\t"
2306  << at5.name() << "\t"
2307  << at6.name() << "\t"
2308  << at7.name() << "\t"
2309  << "ROS:" << "\t"
2310  << at1.name() << "\t"
2311  << at2.name() << "\t"
2312  << at3.name() << "\t"
2313  << std::endl;
2314  }
2315  tr.Debug << "END BOND ANGLES ATOM NAMES" << std::endl;
2316 }
2317 
2318 void
2320 {
2321  tr.Debug << "START PATH DISTANCES" << std::endl;
2322  // print header line
2323  for ( Size i = 1; i <= natoms_; ++i )
2324  {
2325  tr.Debug << "\t" << atoms_[i].name();
2326  }
2327  tr.Debug << std::endl;
2328 
2329  for ( Size j = 1; j <= natoms_; ++j )
2330  {
2331  tr.Debug << atoms_[j].name() << "\t";
2332  for ( Size k = 1; k <= natoms_; ++k )
2333  {
2334  tr.Debug << path_distance_[j][k] << "\t";
2335  }
2336  tr.Debug << std::endl;
2337  }
2338  tr.Debug << "END PATH DISTANCES" << std::endl;
2339 }
2340 
2341 void
2343 {
2344  //std::fill( atom_2_residue_connection_map_.begin(), atom_2_residue_connection_map_.end(), 0 );
2345  for ( Size ii = 1; ii <= natoms_; ++ii ) { atom_2_residue_connection_map_[ ii ].clear(); }
2346 
2347  for ( Size ii = 1; ii <= residue_connections_.size(); ++ii ) {
2348  atom_2_residue_connection_map_[ residue_connections_[ ii ].atomno() ].push_back( ii );
2349  residue_connections_[ ii ].index( ii );
2350  }
2351 }
2352 
2353 void
2355  last_controlling_chi_.resize( natoms_ );
2356  std::fill( last_controlling_chi_.begin(), last_controlling_chi_.end(), 0 );
2357 
2358  /// 1. First we have to mark all the atoms who are direct descendants of the 3rd
2359  /// atom in each chi; this prevents the note_chi_controls_atom recursion from overwriting
2360  /// the last-controlling chi for atoms descending from a particular chi.
2361  for ( Size ii = 1; ii <= nchi(); ++ii ) {
2362  Size const iiat3 = chi_atoms_[ ii ][ 3 ];
2363  // This may be unnecessary; I believe two atoms pair as each other's bases only at the mainchain.
2364  Size const iiat3base = atom_base_[ iiat3 ];
2365  AtomIndices const & ii_nbrs( bonded_neighbor_[ iiat3 ] );
2366  for ( Size jj = 1; jj <= ii_nbrs.size(); ++jj ) {
2367  Size const jj_atom = ii_nbrs[ jj ];
2368  if ( atom_base_[ jj_atom ] == iiat3 && iiat3base != jj_atom ) {
2369  last_controlling_chi_[ jj_atom ] = ii;
2370  }
2371  }
2372  }
2373 
2374  /// 2. Now, lets recurse through all the atoms that are not direct descendants
2375  /// of the 3rd atom in a chi. E.g. chi2 in PHE controls several more atoms than
2376  /// just CD1 and CD2.
2377  for ( Size ii = nchi(); ii >= 1; --ii ) {
2378  /// Note children of atom 3 of chi_ii as being controlled by chi ii.
2379  Size const iiat3 = chi_atoms_[ ii ][ 3 ];
2380  // This may be unnecessary; I believe two atoms pair as each other's bases only at the mainchain.
2381  Size const iiat3base = atom_base_[ iiat3 ];
2382  AtomIndices const & ii_nbrs( bonded_neighbor_[ iiat3 ] );
2383  for ( Size jj = 1; jj <= ii_nbrs.size(); ++jj ) {
2384  Size const jj_atom = ii_nbrs[ jj ];
2385  if ( atom_base_[ jj_atom ] == iiat3 && iiat3base != jj_atom ) {
2386  note_chi_controls_atom( ii, jj_atom );
2387  }
2388  }
2389  }
2390 
2391  /// Now compute the atoms_last_controlled_by_chi_ arrays.
2392 
2393  /// get ready to allocate space in the atoms_last_controlled_by_chi_ arrays
2394  utility::vector1< Size > natoms_for_chi( nchi(), 0 );
2395  for ( Size ii = 1; ii <= natoms_; ++ii ) {
2396  if ( last_controlling_chi_[ ii ] != 0 ) {
2397  ++natoms_for_chi[ last_controlling_chi_[ ii ] ];
2398  }
2399  }
2400 
2401  /// allocate space
2402  atoms_last_controlled_by_chi_.resize( nchi() );
2403  for ( Size ii = 1; ii <= nchi(); ++ii ) {
2404  atoms_last_controlled_by_chi_[ ii ].clear();
2405  atoms_last_controlled_by_chi_[ ii ].reserve( natoms_for_chi[ ii ] );
2406  }
2407 
2408  /// fill the arrays
2409  for ( Size ii = 1; ii <= natoms_; ++ii ) {
2410  if ( last_controlling_chi_[ ii ] != 0 ) {
2411  atoms_last_controlled_by_chi_[ last_controlling_chi_[ ii ]].push_back( ii );
2412  }
2413  }
2414 
2415 }
2416 
2417 /// @details O(N) recursive algorithm for determining the last chi for each atom.
2418 /// Each atom is visited at most twice.
2419 void
2421 {
2422  /// This should never be called on the "root" atom or it will enter an infinite loop
2423  assert( atom_base_[ atom_base_[ atomno ]] != atomno );
2424 
2425  /// End the recursion: this atom already has had it's last chi identified, and it's not
2426  /// the chi we're currently labeling atoms with.
2427  if ( last_controlling_chi_[ atomno ] != 0 && last_controlling_chi_[ atomno ] != chi ) return;
2428 
2429  last_controlling_chi_[ atomno ] = chi;
2430 
2431  AtomIndices const & nbrs( bonded_neighbor_[ atomno ] );
2432  for ( Size ii = 1; ii <= nbrs.size(); ++ii ) {
2433  /// descend into atoms who list atomno as their parent;
2434  /// atom_base_ defines a tree except at the root, where
2435  /// atom_base_[ atom_base_[ ii ]] == ii
2436  if ( atom_base_[ nbrs[ ii ]] == atomno ) {
2437  note_chi_controls_atom( chi, nbrs[ ii ] );
2438  }
2439  }
2440 
2441 }
2442 
2443 void
2445  Size & center,
2446  Size & nbr1,
2447  Size & nbr2
2448 ) const
2449 {
2450  center = 0;
2451  nbr1 = 0;
2452  nbr2 = 0;
2453 
2454  // No backbone atoms, all backbone atoms, or orient mode explicitly set to nbr_atom
2456  // If no backbone atoms (or all bb atoms), assume nbr_atom will be close to center-of-mass.
2457  center = nbr_atom();
2458  // If is hydrogen or too few neighbors, try trekking up the atom tree
2459  while( center > nheavyatoms() || bonded_neighbor(center).size() < 2 ) {
2460  center = atom_base(center);
2461  }
2462  AtomIndices const & nbrs( bonded_neighbor(center) );
2463  // First try to find two neighbors that are heavyatoms
2464  for( Size j=1; j<= nbrs.size(); ++j ) {
2465  Size const nbr( nbrs[j] );
2466  if( nbr <= nheavyatoms() ) {
2467  if ( nbr1 ) nbr2 = nbr;
2468  else nbr1 = nbr;
2469  }
2470  }
2471  // Failing that, just try for two neighbors!
2472  if( !( center && nbr1 && nbr2 ) ) {
2473  for( Size j=1; j<= nbrs.size(); ++j ) {
2474  Size const nbr( nbrs[j] );
2475  if ( nbr1 ) nbr2 = nbr;
2476  else nbr1 = nbr;
2477  }
2478  }
2479  if( !( center && nbr1 && nbr2 ) ) {
2480  // assert() isn't enough for these cases b/c they're typically ligands
2481  // and thus depend on user input -- need to be caught even in release mode.
2482  utility_exit_with_message("Cannot superimpose residues of type "+name());
2483  }
2484  //std::cout << "Superimposing on " << atom_name(center) << " " << atom_name(nbr1) << " " << atom_name(nbr2) << "\n";
2485 
2486  } else {
2487  // look for a backbone atom, one of whose neighbors is a sidechain atom
2488  // center will be this atom
2489  // nbr1 and nbr2 will be the backbone heavyatom nbrs of this atom
2490  // eg center = CA, nbr1 = N. nbr2 = C in the protein case
2491  for ( Size atom_index(1); atom_index <= natoms(); ++atom_index ) {
2492  if ( atom_is_backbone( atom_index ) ) {
2494  center = 0; nbr1 = 0; nbr2 = 0;
2495  for ( Size nbr_index(1); nbr_index <= nbrs.size(); ++nbr_index ) {
2496  Size const nbr( nbrs[ nbr_index ] );
2497  if ( !atom_is_backbone( nbr ) && atom_base( nbr ) == atom_index ) {
2498  // nbr is a sidechain atom that branches from the atom at atom_index
2499  center = atom_index;
2500  } else if ( atom_is_backbone( nbr ) && nbr <= nheavyatoms() ) {
2501  // nbr is a backbone heavy atom neighbor of the atom at atom_index
2502  if ( nbr1 ) nbr2 = nbr;
2503  else nbr1 = nbr;
2504  }
2505  }
2506  } // atom_index is backbone
2507  if ( center && nbr1 && nbr2 ) break;
2508  } // atom_index
2509  }
2510 }
2511 
2512 void
2514 {
2515  if( defined_adducts_.size() == 0 ) return;
2516 
2517  for( Size ii = 1 ; ii <= defined_adducts_.size() ; ++ii) {
2518  Adduct & add( defined_adducts_[ii] );
2519  tr.Debug << "Residue: " << name3() << " Adduct: " << add.adduct_name() <<
2520  " Atom name: " << add.atom_name() << std::endl;
2521  }
2522 }
2523 
2524 void
2526 {
2527 
2528  tr.Debug << "ICoor for " << name3() << std::endl;
2529  for( Size ii = 1 ; ii <= natoms() ; ++ii) {
2530  tr.Debug << " Atom name: " << atom_name( ii ) << " ideal xyz " << atom(ii).ideal_xyz()[0] << " " << atom(ii).ideal_xyz()[1] << " " << atom(ii).ideal_xyz()[2] << std::endl;
2531  }
2532 
2533 }
2534 
2535 
2536 void
2537 ResidueType::show_all_atom_names( std::ostream & out ) const {
2538  // utility::vector1< std::string > names;
2539  for ( utility::vector1< Atom >::const_iterator it = atoms_.begin(), end = atoms_.end();
2540  it != end; ++it ) {
2541  out << it->name() << std::endl;
2542  }
2543 }
2544 
2545 void
2547 {
2548  assert( ncaa_rotlib_n_rots_ == n_bins_per_rot.size() );
2550  for( Size i = 1; i <= ncaa_rotlib_n_rots_; ++i ) {
2551  ncaa_rotlib_n_bins_per_rot_[i] = n_bins_per_rot[i];
2552  }
2553 }
2554 
2555 /// @brief Check if atom is virtual.
2556 bool
2557 ResidueType::is_virtual( Size const & atomno ) const
2558 {
2559  return ( atom_type( atomno ).is_virtual() );
2560 }
2561 
2562 /// @brief Check if residue is 'VIRTUAL_RESIDUE'
2563 bool
2565  return ( has_variant_type( "VIRTUAL_RESIDUE" ) );
2566 }
2567 
2568 
2569 ///////////////////////////////////////////////////////////////////////////////
2570 
2571 } // chemical
2572 } // core