65 #include <numeric/xyz.functions.hh>
66 #include <numeric/NumericTraits.hh>
71 #include <ObjexxFCL/FArray2D.hh>
73 #include <ObjexxFCL/string.functions.hh>
78 #include <basic/Tracer.hh>
79 #include <utility/PyAssert.hh>
82 #include <basic/options/option.hh>
84 #include <basic/options/keys/pH.OptionKeys.gen.hh>
90 #include <utility/vector1.hh>
93 namespace ObjexxFCL {
namespace fmt { } }
using namespace ObjexxFCL::fmt;
99 using namespace ObjexxFCL;
100 using namespace ObjexxFCL::fmt;
102 static basic::Tracer
tr(
"core.chemical.ResidueType");
110 left_justify( trimmed_name ); trim( trimmed_name );
114 ResidueType::ResidueType(
120 atom_types_( atom_types ),
121 elements_( elements ),
122 mm_atom_types_( mm_atom_types ),
123 orbital_types_( orbital_types),
125 residue_type_set_( 0 ),
128 n_hbond_acceptors_(0),
131 n_backbone_heavyatoms_(0),
132 first_sidechain_hydrogen_( 0 ),
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 ),
145 has_sc_orbitals_(false),
146 is_aromatic_( false ),
150 is_carbohydrate_( 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 ),
165 force_nbr_atom_orient_(false),
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),
176 base_restype_name_(
""),
182 tr.Trace <<
"Residue dstor" << std::endl;
190 utility_exit_with_message(
"ResidueType::residue_type_set: pointer is not set!");
239 if ( atm_name ==
"NONE" ) {
271 if ( atm_name ==
"NONE" ) {
366 PyAssert((atomno > 0) && (atomno <=
atoms_.size()),
"ResidueType::atom_type( Size const atomno ): atomno is not in this ResidueType!");
374 PyAssert((index > 0) && (index <=
atoms_.size()),
"ResidueType::atom_name( Size const index ): index is not in this ResidueType!");
375 return atoms_[ index ].name();
382 PyAssert((atomno > 0) && (atomno <=
atom_base_.size()),
"ResidueType::atom_base( Size const atomno ): atomno is not in this ResidueType!");
390 PyAssert((atomno > 0) && (atomno <=
abase2_.size()),
"ResidueType::abase2( Size const atomno ): atomno is not in this ResidueType!");
425 AtomICoor( 0.0, 0.0, 0.0, atom_name, atom_name, atom_name, *
this )
437 std::string const & element_name= (*atom_types_)[type].element();
438 int const element_index =
elements_->element_index(element_name);
440 molar_mass_ += (*elements_)[element_index].weight();
442 tr.Warning <<
"WARNING Elements set undefined." << std::endl;
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 );
572 utility_exit_with_message(
"ResidueType:: shouldnt get here -- resizing in add_atom");
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!" );
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 );
606 utility_exit_with_message(
"ResidueType:: shouldnt get here -- resizing in add_atom");
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!" );
637 std::string message =
"add_bond: atoms " + atom_name1 +
" and " + orbital_name +
" dont exist!";
638 utility_exit_with_message( message );
645 utility_exit_with_message(
"atom_name: " + atom_name1 +
" not found. Improper params file!");
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 );
689 utility_exit_with_message(
"ResidueType:: shouldnt get here -- resizing in add_atom");
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!" );
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!" );
773 chi_rotamers_[chino].push_back( std::make_pair( mean, sdev ) );
790 if ( !
has( atom_name1 ) || !
has( atom_name2 ) ) {
791 utility_exit_with_message(
"set_atom_base: atoms dont exist!" );
802 if ( ( std::find( i1_nbrs.begin(), i1_nbrs.end(), i2 ) == i1_nbrs.end() ) &&
803 !( i1 == 1 && i2 == 1 &&
natoms_ == 1 ) ) {
804 utility_exit_with_message(
"set_atom_base: atoms must be bonded!" );
806 if (
atom_base_.size() <
Size(i1) ) utility_exit_with_message(
"ResidueType:: shouldnt get here!");
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!" );
836 if ( property ==
"POLYMER" ) {
838 }
else if ( property ==
"PROTEIN" ) {
841 }
else if ( property ==
"POLAR" ) {
843 }
else if( property ==
"SC_ORBITALS"){
845 }
else if ( property ==
"CHARGED" ) {
847 }
else if ( property ==
"AROMATIC" ) {
849 }
else if ( property ==
"COARSE" ) {
851 }
else if ( property ==
"DNA" ) {
855 }
else if ( property ==
"RNA" ) {
859 }
else if ( property ==
"CARBOHYDRATE") {
861 }
else if ( property ==
"LIGAND" ) {
863 }
else if ( property ==
"SURFACE" ) {
865 }
else if ( property ==
"LOWER_TERMINUS" ) {
868 }
else if ( property ==
"UPPER_TERMINUS" ) {
871 }
else if ( property ==
"PHOSPHONATE" ) {
874 }
else if ( property ==
"PHOSPHONATE_UPPER" ) {
879 }
else if ( property ==
"TERMINUS" ) {
881 }
else if ( property ==
"ACETYLATED_NTERMINUS" ) {
885 }
else if ( property ==
"METHYLATED_CTERMINUS" ) {
889 }
else if (property ==
"BRANCH_POINT") {
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")) {
904 tr.Warning <<
"WARNING:: unrecognized residue type property: " <<
property << std::endl;
923 if ( property ==
"POLYMER" ) {
925 }
else if ( property ==
"PROTEIN" ) {
927 }
else if ( property ==
"POLAR" ) {
929 }
else if(property ==
"SC_ORBITALS"){
931 }
else if ( property ==
"CHARGED" ) {
933 }
else if ( property ==
"AROMATIC" ) {
935 }
else if ( property ==
"COARSE" ) {
937 }
else if ( property ==
"DNA" ) {
939 }
else if ( property ==
"RNA" ) {
941 }
else if ( property ==
"CARBOHYDRATE") {
943 }
else if ( property ==
"LIGAND" ) {
945 }
else if ( property ==
"SURFACE" ) {
947 }
else if ( property ==
"LOWER_TERMINUS" ) {
950 }
else if ( property ==
"UPPER_TERMINUS" ) {
952 }
else if ( property ==
"TERMINUS" ) {
954 }
else if ( property ==
"PHOSPHONATE" ) {
956 }
else if ( property ==
"PHOSPHONATE_UPPER" ) {
958 }
else if ( property ==
"ACETYLATED_NTERMINUS" ) {
960 }
else if ( property ==
"METHYLATED_CTERMINUS" ) {
963 tr.Warning <<
"WARNING:: unrecognized residuetype property: " <<
property << std::endl;
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!" );
1020 tr.Trace <<
"adding act coord atom: " <<
name_ <<
' ' << atom << std::endl;
1062 assert(
natoms_ == old_natoms );
1067 old2new.resize( old_natoms, 0 );
1071 for (
Size i=1; i<= old_natoms; ++i ) {
1073 tr.Trace <<
"ResidueType::finalize(): delete atom: " <<
atoms_[i].name() << std::endl;
1081 for (
Size i=1; i<= old_natoms; ++i ) {
1085 old_heavyatom_indices.push_back( i );
1094 for (
Size i=1; i<= old_natoms; ++i ) {
1096 ( std::find( old_heavyatom_indices.begin(), old_heavyatom_indices.end(), i ) ==
1097 old_heavyatom_indices.end() ) ) {
1098 old_heavyatom_indices.push_back( i );
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 ] );
1116 old2new[ old_heavy_index ] = new_heavy_index;
1121 for (
Size j=1; j<= nbrs.size(); ++j ) {
1123 Size const old_H_index( nbrs[j] );
1124 if ( keep_me[ old_H_index ] ) {
1126 old2new[ old_H_index ] = new_H_index;
1150 Size const old_natoms( old2new.size() );
1151 assert( old_natoms ==
atoms_.size() );
1165 if ( old_natoms !=
natoms_ ) {
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;
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() );
1190 atoms_[ new_index ] = old_atoms[ old_index ];
1195 atom_base_[ new_index ] = old2new[ old_atom_base[ old_index ] ];
1201 for (
Size j=1, j_end = old_bonded_neighbor[ old_index ].
size(); j<= j_end; ++j )
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 ] );
1209 for(
Size j=1, j_end=old_bonded_neighbor_type[old_index].
size(); j<=j_end; ++j)
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]);
1216 for (
Size j=1, j_end = old_cut_bond_neighbor[ old_index ].
size(); j<= j_end; ++j )
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 ] );
1223 parents_[ new_index ] = old_parents[ old_index ];
1225 for (
Size i=1; i<= 3; ++i ) {
1229 assert( stub_atom.
atomno() );
1238 orbital_index_end = orbital_indices.end();
1247 if ( stub1 == 0 || stub2 == 0 || stub3 == 0) {
1273 for (
Size j=1; j<= 4; ++j ) {
1308 for (
Size j = 1; j <= 3; ++j ) {
1440 for (
Size ii=1, ii_end=
accpt_pos_.size(); ii<= ii_end; ++ii ) {
1443 assert( i_base != 0 );
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 );
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 ];
1465 }
else if ( i_nbrs[1] == i_base ) {
1489 for (
Size central_atom1 = 1; central_atom1 <
natoms_; ++central_atom1 ) {
1490 for (
Size central_atom2 = central_atom1+1; central_atom2 <=
natoms_; ++central_atom2 ) {
1499 if ( (
path_distance_[ central_atom1 ][ i ] == 1 ) && ( i != central_atom2 ) ) {
1500 ca1d1.push_back( i );
1505 if ( (
path_distance_[ central_atom2 ][ i ] == 1 ) && ( i != central_atom1 ) ) {
1506 ca2d1.push_back( i );
1512 terminal_atom1 != ca1d1.end(); ++terminal_atom1 ) {
1514 terminal_atom2 != ca2d1.end(); ++terminal_atom2 ) {
1515 dihedral_atom_set temp( *terminal_atom1, central_atom1, central_atom2, *terminal_atom2 );
1538 for (
Size central_atom = 1; central_atom <=
natoms_; ++central_atom ) {
1541 Size const num_bonded_neighbors( bonded_neighbors.size() );
1544 for (
Size i = 1; i < num_bonded_neighbors; ++i ) {
1545 for (
Size j = i+1; j <= num_bonded_neighbors; ++j ) {
1577 Size const ii_num_bonded_neighbors( ii_bonded_neighbors.size() );
1579 for (
Size jj = 1; jj <= ii_num_bonded_neighbors; ++jj ) {
1580 Size const jj_atom = ii_bonded_neighbors[ jj ];
1593 Size const jj_num_bonded_neighbors( jj_bonded_neighbors.size() );
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;
1695 if ( ! basic::options::option[ basic::options::OptionKeys::pH::pH_mode ].user() ) {
1706 int this_variant_count_offset( 0 );
1709 this_variant_count_offset = 1;
1717 int other_variant_count_offset( 0 );
1719 other_variant_count_offset = 1;
1722 return ( (
variant_types_.size() - this_variant_count_offset ) ==
1730 int this_variant_count_offset( 0 );
1733 this_variant_count_offset = 1;
1741 int other_variant_count_offset( 0 );
1743 other_variant_count_offset = 1;
1746 return ( (
variant_types_.size() - this_variant_count_offset ) ==
1754 std::map< std::string, int >::const_iterator iter
1770 std::map< std::string, int >::const_iterator iter
1775 if ( name ==
"CA" && !
is_protein() )
return 1;
1777 tr.Error <<
"atom name : " << name <<
" not available in residue " <<
name3() << std::endl;
1779 tr.Error << std::endl;
1780 utility_exit_with_message(
"unknown atom_name: " +
name3() +
" " + name );
1782 return iter->second;
1789 std::map< std::string, int >::const_iterator iter
1792 utility_exit_with_message(
"unknown orbital_name: " +
name3() +
" " + name );
1794 return iter->second;
1817 return atoms_[ atm ].icoor();
1862 bool const update_xyz
1866 AtomICoor const ic( index, phi, theta, d, stub_atom1, stub_atom2, stub_atom3, *
this );
1868 Size const atomno(
id.atomno() );
1869 switch (
id.type() ) {
1871 if (
atoms_.size() < atomno ) utility_exit_with_message(
"ResidueType:: shouldn't get here!");
1872 atoms_[ atomno ].icoor( ic );
1874 if ( ( stub_atom1 != atm ) &&
has( stub_atom1 ) &&
1898 utility_exit_with_message(
"unrecognized stub atom id type!" );
1911 bool const update_xyz
1915 AtomICoor const ic( phi, theta, d, stub_atom1, stub_atom2, stub_atom3, *
this );
1917 Size const atomno(
id.atomno() );
1918 switch (
id.type() ) {
1920 if (
atoms_.size() < atomno ) utility_exit_with_message(
"ResidueType:: shoudnt get here!");
1921 atoms_[ atomno ].icoor( ic );
1923 if ( ( stub_atom1 != atm ) &&
has( stub_atom1 ) &&
1947 utility_exit_with_message(
"unrecognized stub atom id type!" );
1976 orbitals_[ orb_indx ].new_icoor( new_icoor );
2000 Vector total(0.0,0.0,0.0);
2003 total +=
atoms_[index].ideal_xyz();
2019 assert(min_index != 0);
2045 parent_stub1 =
atom_name(current_atom_index);
2059 parent_stub1 =
atom_name(current_atom_index);
2066 for(
core::Size index = 1; index <children.size();++index)
2078 parents_[child_index] = current_atom_index;
2079 if((current_atom_index ==
nbr_atom_) && (previous_sibling == parent_stub2))
2081 child_stub3 = parent_stub3;
2086 previous_sibling =
atom_name(child_index);
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;
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) )
2119 phi = numeric::dihedral_radians<core::Real>(child_xyz,stub1_xyz,stub2_xyz,stub3_xyz);
2124 set_icoor(child,phi,theta,distance,stub_atom1,stub_atom2,stub_atom3);
2144 atoms_[index].ideal_xyz( xyz_in );
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() );
2219 // rotlib_ = scoring::ScoringManager::get_instance()->
2220 // get_RotamerLibrary().get_rsd_library(*this);
2223 // bRotamers_ = ( rotlib_ != 0 );
2224 //} else rotlib_ = 0; //nchi == 0
2233 ResidueType::set_RotamerLibrary(pack::dunbrack::SingleResidueRotamerLibraryCOP rotlib)
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);
2243 tr.Debug <<
"START DIHEDRAL ANGLES ATOM NAMES" << std::endl;
2257 tr.Debug <<
"PDB:" <<
"\t"
2268 << at5.
name() <<
"\t"
2269 << at6.
name() <<
"\t"
2270 << at7.
name() <<
"\t"
2271 << at8.
name() <<
"\t"
2273 << at1.
name() <<
"\t"
2274 << at2.
name() <<
"\t"
2275 << at3.
name() <<
"\t"
2276 << at4.
name() <<
"\t"
2279 tr.Debug <<
"END DIHEDRAL ANGLES ATOM NAMES" << std::endl;
2285 tr.Debug <<
"START BOND ANGLES ATOM NAMES" << std::endl;
2297 tr.Debug <<
"PDB:" <<
"\t"
2306 << at5.
name() <<
"\t"
2307 << at6.
name() <<
"\t"
2308 << at7.
name() <<
"\t"
2310 << at1.
name() <<
"\t"
2311 << at2.
name() <<
"\t"
2312 << at3.
name() <<
"\t"
2315 tr.Debug <<
"END BOND ANGLES ATOM NAMES" << std::endl;
2321 tr.Debug <<
"START PATH DISTANCES" << std::endl;
2325 tr.Debug <<
"\t" <<
atoms_[i].name();
2327 tr.Debug << std::endl;
2331 tr.Debug <<
atoms_[j].name() <<
"\t";
2336 tr.Debug << std::endl;
2338 tr.Debug <<
"END PATH DISTANCES" << std::endl;
2361 for (
Size ii = 1; ii <=
nchi(); ++ii ) {
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 ) {
2377 for (
Size ii =
nchi(); ii >= 1; --ii ) {
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 ) {
2403 for (
Size ii = 1; ii <=
nchi(); ++ii ) {
2432 for (
Size ii = 1; ii <= nbrs.size(); ++ii ) {
2464 for(
Size j=1; j<= nbrs.size(); ++j ) {
2465 Size const nbr( nbrs[j] );
2467 if ( nbr1 ) nbr2 = nbr;
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;
2479 if( !( center && nbr1 && nbr2 ) ) {
2482 utility_exit_with_message(
"Cannot superimpose residues of type "+
name());
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 ] );
2502 if ( nbr1 ) nbr2 = nbr;
2507 if ( center && nbr1 && nbr2 )
break;
2520 " Atom name: " << add.
atom_name() << std::endl;
2528 tr.Debug <<
"ICoor for " <<
name3() << std::endl;
2541 out << it->name() << std::endl;