37 #include <basic/Tracer.hh>
41 #include <ObjexxFCL/string.functions.hh>
46 #include <utility/file/FileName.hh>
47 #include <utility/file/file_sys_util.hh>
50 #include <numeric/conversions.hh>
53 #include <platform/types.hh>
56 #include <utility/Bound.hh>
57 #include <utility/vector1.hh>
58 #include <utility/io/izstream.hh>
59 #include <utility/keys/AutoKey.hh>
60 #include <utility/keys/SmallKeyVector.hh>
61 #include <numeric/xyz.functions.hh>
62 #include <ObjexxFCL/Dimension.hh>
63 #include <ObjexxFCL/DynamicIndexRange.hh>
64 #include <ObjexxFCL/FArray.hh>
65 #include <ObjexxFCL/FArray2D.hh>
66 #include <basic/options/keys/corrections.OptionKeys.gen.hh>
67 #include <basic/options/keys/in.OptionKeys.gen.hh>
68 #include <basic/options/option.hh>
69 #include <boost/foreach.hpp>
72 #define foreach BOOST_FOREACH
75 namespace ObjexxFCL { }
using namespace ObjexxFCL;
88 static basic::Tracer
tr(
"core.chemical");
113 switch (
id.type() ) {
115 return AtomID(
id.atomno(), 1 );
116 case ICoorAtomID::CONNECT:
117 return AtomID(
id.atomno(), 2 );
118 case ICoorAtomID::POLYMER_LOWER:
119 return AtomID( 1, 3 );
120 case ICoorAtomID::POLYMER_UPPER:
121 return AtomID( 2, 3 );
123 utility_exit_with_message(
"unrecognized stub atom id type!" );
141 utility_exit_with_message(
"Cannot find file '"+filename+
"'");
143 utility::io::izstream data( filename.c_str() );
144 if ( !data.good() ) {
145 utility_exit_with_message(
"Cannot open file '"+filename+
"'");
147 return read_topology_file(data, atom_types, elements, mm_atom_types, orbital_atom_types, rsd_type_set);
158 utility::io::izstream & data,
169 using numeric::conversions::radians;
170 using numeric::conversions::degrees;
172 using namespace basic;
180 while ( getline( data, line ) ) {
181 std::istringstream l( line );
183 if ( line.size() < 1 )
continue;
184 std::string::size_type pound= line.find(
'#', 0);
185 if( pound == std::string::npos ) lines.push_back( line );
187 std::string no_comment_line= line.substr(0, pound);
188 lines.push_back(no_comment_line);
191 tr.Debug <<
"Read " << lines.size() <<
" lines from file: " <<
211 rsd->residue_type_set( rsd_type_set );
214 Size const nlines( lines.size() );
216 for (
Size i=1; i<= nlines; ++i ) {
218 if (line.size() > 0) {
219 while (line.substr(line.size()-1) ==
" ") {
220 line = line.substr(0,line.size()-1);
221 if (line.size() == 0)
break;
225 std::istringstream l( line );
230 if ( tag !=
"ATOM" )
continue;
243 l >> tag;
std::string const mm_atom_type_name( tag );
249 float parse_charge(charge);
254 if ( ! basic::options::option[ basic::options::OptionKeys::corrections::chemical::parse_charge ]() ) {
255 rsd->add_atom( atom_name, atom_type_name, mm_atom_type_name, charge );
258 rsd->add_atom( atom_name, atom_type_name, mm_atom_type_name, parse_charge );
267 utility_exit_with_message(
"Residue topology file '" +
filename +
"' does not contain valid ATOM records.");
271 bool found_AA_record =
false;
272 bool found_PDB_ROTAMERS_record =
false;
274 for (
Size i=1; i<= nlines; ++i ) {
276 std::istringstream l( line );
279 if ( l.fail() )
continue;
280 if ( tag ==
"CONNECT" ) {
283 rsd->add_residue_connection( atom1);
285 }
else if ( tag ==
"TYPE" ) {
288 if ( tag ==
"POLYMER" ) {
289 rsd->add_property( tag );
290 }
else if ( tag ==
"LIGAND" ) {
291 rsd->add_property( tag );
298 }
else if ( tag ==
"BOND" ) {
300 rsd->add_bond( atom1, atom2 );
302 }
else if ( tag ==
"CUT_BOND" ) {
304 rsd->add_cut_bond( atom1, atom2 );
306 }
else if ( tag ==
"CHI" ) {
308 l >> chino >> atom1 >> atom2 >> atom3 >> atom4;
309 rsd->add_chi( chino, atom1, atom2, atom3, atom4 );
310 }
else if ( tag ==
"PROTON_CHI") {
311 Size chino, nsamples, nextra_samples;
317 for (
Size ii = 1; ii <= nsamples; ++ii ) {
323 for (
Size ii = 1; ii <= nextra_samples; ++ii ) {
324 l >> extra_samples[ ii ];
326 rsd->set_proton_chi( chino, samples, extra_samples );
328 }
else if ( tag ==
"NBR_ATOM" ) {
330 rsd->nbr_atom( atom1 );
332 }
else if ( tag ==
"NBR_RADIUS" ) {
335 rsd->nbr_radius( radius );
336 }
else if ( tag ==
"ORIENT_ATOM" ) {
338 if ( tag ==
"NBR" ) {
339 rsd->force_nbr_atom_orient(
true);
340 }
else if ( tag ==
"DEFAULT" ) {
341 rsd->force_nbr_atom_orient(
false);
343 utility_exit_with_message(
"Unknown ORIENT_ATOM mode: " + tag );
345 }
else if ( tag ==
"PROPERTIES" ) {
347 while ( !l.fail() ) {
348 rsd->add_property( tag );
352 }
else if ( tag ==
"VARIANT" ) {
354 while ( !l.fail() ) {
355 rsd->add_variant_type( tag );
358 }
else if ( tag ==
"FIRST_SIDECHAIN_ATOM" ) {
361 if ( tag ==
"NONE" ) {
363 for (
Size j=1; j<= rsd->natoms(); ++j ) {
364 rsd->set_backbone_heavyatom( rsd->atom_name(j) );
366 }
else if ( rsd->has( tag ) ) {
367 for (
Size j=1; j< rsd->atom_index( tag ); ++j ) {
368 rsd->set_backbone_heavyatom( rsd->atom_name(j) );
372 }
else if ( tag ==
"IO_STRING" ) {
373 assert( line.size() >= 15 );
374 std::string const three_letter_code( line.substr(10,3) ),
375 one_letter_code( line.substr(14,1) );
376 rsd->name3( three_letter_code );
377 rsd->name1( one_letter_code[0] );
379 }
else if ( tag ==
"AA" ) {
382 found_AA_record =
true;
384 }
else if ( tag ==
"ROTAMER_AA" ) {
386 rsd->rotamer_aa( tag );
388 }
else if ( tag ==
"NAME" ) {
392 }
else if ( tag ==
"CHI_ROTAMERS" ) {
397 while ( !l.fail() ) {
398 rsd->add_chi_rotamer( chino, mean, sdev );
401 }
else if ( tag ==
"PDB_ROTAMERS" ) {
402 found_PDB_ROTAMERS_record =
true;
403 l >> pdb_rotamers_filename;
404 }
else if ( tag ==
"ACT_COORD_ATOMS" )
408 if ( atom1 ==
"END")
break;
409 rsd->add_actcoord_atom( atom1 );
411 }
else if ( tag ==
"LOWER_CONNECT" ) {
413 rsd->set_lower_connect_atom( atom1 );
414 }
else if ( tag ==
"UPPER_CONNECT" ) {
416 rsd->set_upper_connect_atom( atom1 );
417 }
else if ( tag ==
"ADDUCT" ) {
418 std::string adduct_name, adduct_atom_name, adduct_atom_type, adduct_mm_type;
419 Real adduct_q, adduct_d, adduct_theta, adduct_phi;
420 l >> adduct_name >> adduct_atom_name;
421 l >> adduct_atom_type >> adduct_mm_type;
422 l >> adduct_q >> adduct_phi >> adduct_theta >> adduct_d;
423 l >> atom1 >> atom2 >> atom3;
424 ObjexxFCL::lowercase(adduct_name);
425 Adduct new_adduct( adduct_name, adduct_atom_name,
426 adduct_atom_type, adduct_mm_type, adduct_q,
427 adduct_phi, adduct_theta, adduct_d,
428 atom1, atom2, atom3 );
429 rsd->add_adduct( new_adduct );
430 }
else if ( tag ==
"NCAA_ROTLIB_PATH" ) {
433 rsd->set_ncaa_rotlib_path( path );
434 rsd->set_use_ncaa_rotlib(
true );
435 }
else if ( tag ==
"NCAA_ROTLIB_NUM_ROTAMER_BINS" ) {
439 rsd->set_ncaa_rotlib_n_rotameric_bins( n_rots );
440 n_bins_per_rot.resize( n_rots );
441 for(
Size i = 1; i <= n_rots; ++i ) {
444 n_bins_per_rot[i] = bin_size;
446 rsd->set_ncaa_rotlib_n_bin_per_rot( n_bins_per_rot );
482 if ( !found_AA_record ) {
483 basic::Warning() <<
"No AA record found for " << rsd->name() <<
"; assuming " <<
name_from_aa( rsd->aa() ) << std::endl;
491 std::map< std::string, Vector > rsd_xyz;
493 for (
Size i=1; i<= nlines; ++i ) {
496 std::istringstream l( line );
497 std::string tag, child_atom, parent_atom, angle_atom, torsion_atom;
502 if ( tag !=
"ICOOR_INTERNAL" )
continue;
504 l >> child_atom >> phi >> theta >> d >> parent_atom >> angle_atom >> torsion_atom;
506 phi = radians(phi); theta = radians(theta);
511 if ( child_atom == parent_atom ) {
512 assert( rsd_xyz.empty() );
513 rsd_xyz[ child_atom ] =
Vector( 0.0 );
515 }
else if ( child_atom == angle_atom ) {
516 assert( rsd_xyz.size() == 1 && rsd_xyz.count( parent_atom ) );
517 rsd_xyz[ child_atom ] =
Vector( d, 0.0, 0.0 );
521 if ( child_atom == torsion_atom ) {
522 assert( rsd_xyz.size() == 2 );
523 assert( rsd_xyz.count( parent_atom ) );
524 assert( rsd_xyz.count( angle_atom ) );
525 torsion_xyz =
Vector( 1.0, 1.0, 0.0 );
527 assert( rsd_xyz.count( parent_atom ) && rsd_xyz.count( angle_atom ) && rsd_xyz.count( torsion_atom ) );
528 torsion_xyz = rsd_xyz[ torsion_atom ];
530 kinematics::Stub const stub( rsd_xyz[ parent_atom ], rsd_xyz[ angle_atom ], torsion_xyz );
531 rsd_xyz[ child_atom ] = stub.
spherical( phi, theta, d );
537 if ( child_atom !=
"UPPER" && child_atom !=
"LOWER" && child_atom.substr(0,4) !=
"CONN" ) {
539 if ( child_atom == parent_atom ) {
542 rsd->set_atom_base( child_atom, child_atom );
544 rsd->set_atom_base( child_atom, angle_atom );
547 rsd->set_atom_base( child_atom, parent_atom );
552 rsd->set_icoor( i, child_atom, phi, theta, d, parent_atom, angle_atom, torsion_atom );
561 rsd->set_ideal_xyz( name,
Vector(0.0) );
565 for (
Size i=1; i<= natoms; ++i ) {
568 assert( rsd_xyz.count( name ) );
569 rsd->set_ideal_xyz( name, rsd_xyz[ name ] );
577 if ( rsd->is_polymer() ) {
578 uint upper_connect( rsd->upper_connect_atom() ), lower_connect( rsd->lower_connect_atom() );
581 if ( upper_connect && lower_connect ) {
584 uint atom( lower_connect );
585 while ( atom != upper_connect ) {
586 mainchain.push_back( atom );
588 int min_d(
D( atom, upper_connect ) );
589 uint next_atom( atom );
593 for (
uint i=1; i<= nbrs.size(); ++i ) {
594 uint const nbr( nbrs[i] );
595 if (
D( nbr, upper_connect ) < min_d ) {
596 min_d =
D( nbr, upper_connect );
600 assert( next_atom != atom );
604 mainchain.push_back( upper_connect );
605 rsd->set_mainchain_atoms( mainchain );
747 if( found_PDB_ROTAMERS_record ) {
748 using namespace utility::file;
752 rot_file.vol( this_file.vol() );
753 rot_file.path( this_file.path() );
755 rsd->set_RotamerLibraryName( rot_file() );
757 tr.Debug <<
"Setting up conformer library for " << rsd->name() << std::endl;
781 using numeric::conversions::radians;
782 using numeric::conversions::degrees;
786 std::ofstream out( filename.c_str() );
788 out <<
"#rosetta residue topology file \n";
789 out <<
"#version ??? \n";
790 out <<
"#This automatically generated file is not really formatted, but should work, excpet that enums for connection types \n# are given in numbers and not strings. \n";
793 out <<
"NAME " << rsd.
name() <<
" \n";
794 out <<
"IO_STRING " << rsd.
name3() <<
" " << rsd.
name1() <<
" \n";
795 if( rsd.
is_polymer() ) { out <<
"TYPE POLYMER \n"; }
796 else if ( rsd.
is_ligand() ) { out <<
"TYPE LIGAND \n"; }
797 else if ( rsd.
is_surface() ) { out <<
"TYPE SURFACE \n"; }
798 out <<
"AA " << rsd.
aa() <<
" \n";
805 out << atom_out <<
" " << rsd.
atom(i).
charge() <<
" \n";
816 foreach(
Size atom_index, rsd.
nbrs(i)){
817 if( atom_index > i ) {
825 for(
Size i=1; i <= rsd.
nchi(); i++){
828 for(AtomIndices::iterator at_it = atoms_this_chi.begin(); at_it != atoms_this_chi.end(); at_it++ ){
835 Size n_proton_chi(0);
836 for(
Size i=1; i <= rsd.
nchi(); i++){
840 out <<
"PROTON_CHI " << i <<
" SAMPLES ";
843 out << pchi_samples.size() ;
844 for(
Size j = 1; j <= pchi_samples.size(); j++){ out <<
" " << pchi_samples[j]; }
845 out <<
" EXTRA " << pchi_extra.size();
846 for(
Size j = 1; j <= pchi_extra.size(); j++){ out <<
" " << pchi_extra[j]; }
855 if(rsd.
is_DNA() ) { out <<
" DNA"; }
856 if(rsd.
is_RNA() ) { out <<
" RNA"; }
857 if(rsd.
is_polar() ) { out <<
" POLAR"; }
866 out <<
"NBR_RADIUS " << rsd.
nbr_radius() <<
" \n";
871 out <<
"ACT_COORD_ATOMS ";
873 for(AtomIndices::iterator at_it = act_atoms.begin(); at_it != act_atoms.end(); at_it++ ){
883 out <<
"ICOOR_INTERNAL " << rsd.
atom_name( i ) <<
" " << degrees( cur_icoor.
phi() ) <<
" ";
884 out << degrees( cur_icoor.
theta() ) <<
" " << cur_icoor.
d();