29 #include <utility/io/izstream.hh>
30 #include <utility/exit.hh>
31 #include <utility/assert.hh>
32 #include <utility/string_util.hh>
33 #include <basic/Tracer.hh>
34 #include <basic/options/option.hh>
36 #include <basic/options/keys/packing.OptionKeys.gen.hh>
57 #include <basic/options/keys/run.OptionKeys.gen.hh>
59 #include <utility/vector1.hh>
71 static basic::Tracer
TR(
"core.pack.task.ResfileReader");
76 using std::istringstream;
78 using std::stringstream;
85 commands_( pose.total_residue() )
90 bool have_read_start_token =
false;
102 if (!tokens.size())
continue;
105 if (!have_read_start_token) {
109 residue_range_commands, residue_chain_commands);
113 if (!have_read_start_token) {
115 <<
"Reached the end of resfile without finding a 'START' token." << endl
116 <<
"No residue-specific behavior specified in resfile." << endl;
122 if(!residue_range_commands[i].empty()){
124 residue_range_commands[i].begin(), residue_range_commands[i].
end());
125 }
else if(!residue_chain_commands[i].empty()){
127 residue_chain_commands[i].begin(), residue_chain_commands[i].
end());
136 std::list< ResfileCommandCOP >
const &
146 if ( resid >
commands_.size() || resid == 0 ) {
147 utility_exit_with_message(
"Residue index out of bounds: resid=" +
148 utility::to_string( resid ) +
" with only " +
149 utility::to_string(
commands_.size() ) +
" residues total." );
154 std::list< ResfileCommandCOP >
const &
157 if ( resid >
commands_.size() || resid == 0 ) {
158 utility_exit_with_message(
"Residue index out of bounds: resid=" +
159 utility::to_string( resid ) +
" with only " +
160 utility::to_string(
commands_.size() ) +
" residues total." );
168 map< string, ResfileCommandOP >
const & command_map,
170 bool & have_read_start_token
173 if (
get_token( 1, tokens) ==
"START" ) {
174 have_read_start_token =
true;
176 Size which_token = 1, ntokens = tokens.size();
177 while(which_token <= ntokens){
182 command->initialize_from_tokens(tokens, which_token, 0);
204 map< string, ResfileCommandOP >
const & command_map,
206 vector1< std::list<ResfileCommandOP > > & residue_range_commands,
207 vector1< std::list<ResfileCommandOP > > & residue_chain_commands
209 Size which_token = 1, ntokens(tokens.size());
210 int PDBnum, PDBnum_end;
211 char icode, icode_end, chain;
215 PDBnum, PDBnum_end, icode, icode_end, chain, id_type);
217 bool found_commands(
false);
222 while (which_token <= ntokens) {
227 command->initialize_from_tokens( tokens, which_token, resid );
229 found_commands =
true;
233 Size const resid_end(
locate_resid(pose, chain, PDBnum_end, icode_end, lineno));
234 if(resid_start >= resid_end){
235 stringstream err_msg;
237 <<
"On line " << lineno <<
", "
238 <<
"the start residue (PDBnum=" << PDBnum;
240 err_msg <<
", icode=" << icode;
243 <<
", chain=" << (chain ==
' ' ?
'_' : chain) <<
") "
244 <<
"does not come before the end residue "
245 <<
"(PDBnum=" << PDBnum_end;
246 if(icode_end !=
' '){
247 err_msg <<
", icode=" << icode_end;
250 <<
", chain=" << (chain ==
' ' ?
'_' : chain) <<
").";
254 while ( which_token <= ntokens ) {
259 Size const saved_which_token(which_token);
262 for(
Size i = resid_start; i <= resid_end; ++i){
263 which_token_i = saved_which_token;
265 command_i->initialize_from_tokens(tokens, which_token_i, i);
266 residue_range_commands[i].push_back(command_i);
268 which_token = which_token_i;
269 found_commands =
true;
273 stringstream err_msg;
275 <<
"On line " << lineno <<
", "
276 <<
"attemting to set task for all residues in a chain, however the pose does not have a PdbInfo object, which is used to look up which residues are part of which chain. Often the PdbInfo object is setup when the pose is intialized. Please check your protocol.";
277 utility_exit_with_message(err_msg.str());
279 bool found_a_residue_on_chain(
false);
280 while ( which_token <= ntokens ) {
285 Size const saved_which_token(which_token);
288 if(pose.
pdb_info()->chain(i) == chain){
289 found_a_residue_on_chain =
true;
290 which_token_i = saved_which_token;
292 command_i->initialize_from_tokens(tokens, which_token_i, i);
293 residue_chain_commands[i].push_back(command_i);
296 which_token = which_token_i;
297 found_commands =
true;
299 if(!found_a_residue_on_chain){
300 stringstream err_msg;
302 <<
"On line " << lineno <<
", "
303 <<
"there are no residues with chain '"
304 << (chain ==
' ' ?
'_' : chain) <<
"'.";
310 runtime_assert(
false);
314 stringstream err_msg;
316 <<
"On line " << lineno <<
", "
317 <<
"no commands are specified.";
335 string token(
get_token(which_token, tokens));
337 if(*token.begin() ==
'*'){
341 if(token.length() > 1){
342 stringstream err_msg;
344 <<
"On line " << lineno <<
", "
345 <<
"malformed residue identifier specification involving '*'";
367 stringstream err_msg;
369 <<
"On line " << lineno <<
", "
370 <<
"malformed residue identifier.";
376 token =
get_token( which_token, tokens );
389 token =
get_token(which_token-1, tokens,
false);
390 if (token.length() != 1){
391 stringstream err_msg;
393 <<
"On line " << lineno <<
", "
394 <<
"the chain identifier '" << token <<
"' "
395 <<
"must be just a single character in [_A-Za-z] "
396 <<
"(note the chain identifier is case sensitive).";
400 if (chain ==
'_') chain =
' ';
402 stringstream err_msg;
404 <<
"On line " << lineno <<
", "
405 <<
"The chain identifier '" << chain <<
"' "
406 <<
"is not in [_A-Za-z] "
407 <<
"(note the chain identifier is case sensitive).";
414 string const & token,
417 char & icode)
const {
419 istringstream PDBnum_s;
420 if ( std::isalpha( *token.rbegin() ) ) {
421 PDBnum_s.str(token.substr(0, token.length() - 1));
422 icode = *token.rbegin();
429 if(!(PDBnum_s >> PDBnum) || PDBnum_s.get(remaining)){
430 stringstream err_msg;
432 <<
"On line " << lineno <<
", "
433 <<
"the token '" << token <<
"' "
434 <<
"is not a valid <PDBNUM>[<ICODE>] identifier.";
455 resid = pose.
pdb_info()->pdb2pose().find( chain, PDBnum, icode );
459 std::stringstream err_msg;
460 err_msg <<
"On line " << lineno <<
", the pose does not have residue with chain=" << chain <<
", PDBnum=" << PDBnum;
462 err_msg <<
", icode=" << icode;
474 Size const which_token,
476 std::map< string, ResfileCommandOP >
const & command_map,
480 std::map< string, ResfileCommandOP >::const_iterator command(
481 command_map.find(
get_token(which_token, tokens)));
483 if (command == command_map.end()) {
484 std::stringstream err_msg;
486 <<
"On line " << lineno
487 <<
" command '" <<
get_token(which_token, tokens) <<
"' is not recognized.";
490 return(command->second->clone());
504 assert(
get_token( which_token, tokens ) == name() );
526 assert(
get_token( which_token, tokens ) == name() );
546 utility::vector1< std::string >
const & tokens,
552 assert(
get_token( which_token, tokens ) == name() );
586 assert(
get_token( which_token, tokens ) == name() );
637 using namespace chemical;
640 assert(
get_token( which_token, tokens ) == name() );
643 if ( which_token == tokens.size() ) {
644 std::stringstream err_msg;
645 err_msg <<
"PIKAA must be followed by a string of allowed amino acids.";
654 for (
Size ii = 0; ii < aas_to_keep.size(); ++ii ) {
657 if (
size_t(aa) <= keep_canonical_aas_.size() ) {
658 keep_canonical_aas_[ aa ] =
true;
662 na_allowed_.push_back( aa );
665 TR <<
"Ignoring unknown one-letter amino acid code " << aas_to_keep[ ii ] <<
" while parsing PIKAA mode for residue " << resid <<
"." << std::endl;
680 utility_exit_with_message(
"PIKAA Resfile Command used uninitialized" );
683 for ( std::list< chemical::AA >::const_iterator
684 iter = na_allowed_.begin(), iter_end = na_allowed_.end();
685 iter != iter_end; ++iter ) {
700 using namespace chemical;
703 assert(
get_token( which_token, tokens ) == name() );
705 if ( which_token == tokens.size() ) {
706 std::stringstream err_msg;
707 err_msg <<
"PIKNA must be followed by nucleic acids in one-letter format.";
715 for ( std::string::const_iterator letter( nas_string.begin() );
716 letter != nas_string.end(); ++letter ) {
719 if ( *letter ==
'A' || *letter ==
'a' ) na =
na_ade;
720 else if ( *letter ==
'C' || *letter ==
'c' ) na =
na_cyt;
721 else if ( *letter ==
'G' || *letter ==
'g' ) na =
na_gua;
722 else if ( *letter ==
'T' || *letter ==
't' ) na =
na_thy;
724 std::stringstream err_msg;
725 TR <<
"Ignoring unknown one-letter nucleic acid code. " << *letter <<
" while parsing PIKNA option for residue " << resid <<
".";
728 keep_nas_.push_back( na );
752 using namespace chemical;
755 assert( tokens[ which_token ] == name() );
756 if ( which_token == tokens.size() ) {
757 TR.Error <<
"RESFILE ERROR: PIKRNA must be followed by a string of allowed "
758 <<
"nucleic acids in single-letter format" << std::endl;
761 std::string const & nas_string( tokens[ ++which_token ] );
765 for ( std::string::const_iterator letter( nas_string.begin() );
766 letter != nas_string.end(); ++letter ) {
769 if ( *letter ==
'A' || *letter ==
'a' ) na =
na_rad;
770 else if ( *letter ==
'C' || *letter ==
'c' ) na =
na_rcy;
771 else if ( *letter ==
'G' || *letter ==
'g' ) na =
na_rgu;
772 else if ( *letter ==
'U' || *letter ==
'u' ) na =
na_ura;
774 TR.Error <<
"RESFILE ERROR: unknown one-letter nucleic acid code " << *letter
775 <<
" while parsing PIKRNA option for residue " << resid << std::endl;
778 keep_rnas_.push_back( na );
790 for (
Size ii = 1; ii <= keep_rnas_.size(); ++ii ) {
806 using namespace chemical;
808 assert(
get_token( which_token, tokens ) == name() );
816 for (
Size ii = 0; ii < aas_to_exclude.size(); ++ii ) {
821 std::stringstream err_msg;
822 TR <<
"Ignoring Unknown one-letter amino acid code "<< aas_to_exclude[ ii ] <<
" while parsing NOTAA option for residue " << resid <<
".";
850 assert(
get_token( which_token, tokens ) == name() );
876 assert(
get_token( which_token, tokens ) == name() );
886 using namespace chemical;
893 restype_iter != restype_iter_end; ++restype_iter ) {
895 std::stringstream err_msg;
896 err_msg <<
"POLAR mode read for residue " << resid <<
" which has been instructed to use non-canonical amino acids.";
900 if ( (*restype_iter)->is_polar() ) {
901 keep_aas[ (*restype_iter)->aa() ] =
true;
919 assert(
get_token( which_token, tokens ) == name() );
929 using namespace chemical;
936 restype_iter != restype_iter_end; ++restype_iter ) {
938 std::stringstream err_msg;
939 err_msg <<
"APOLAR mode read for residue " << resid <<
" which has been instructed to use non-canonical amino acids.";
943 if ( ! (*restype_iter)->is_polar() ) {
944 keep_aas[ (*restype_iter)->aa() ] =
true;
959 utility::vector1< std::string >
const & tokens,
965 assert(
get_token( which_token, tokens ) == name() );
966 TR <<
"RESFILE NOTE: APOLA command deprecated. Use APOLAR command instead. Treating as APOLAR command." << std::endl;
993 assert(
get_token( which_token, tokens ) == name() );
995 if ( which_token == tokens.size() ) {
996 std::stringstream err_msg;
997 err_msg <<
"EX command must be followe by a chi-id or \"ARO\" for reside " << resid <<
".";
1001 aro_specified_ =
false;
1002 if (
get_token( which_token + 1, tokens ) ==
"ARO" ) {
1003 aro_specified_ =
true;
1005 if ( which_token == tokens.size() ) {
1006 std::stringstream err_msg;
1007 err_msg <<
"EX ARO command must be followed by a chi-id for residue " << resid <<
".";
1012 which_chi_ = atoi(
get_token( which_token, tokens ).c_str() );
1013 Size which_chi_token = which_token;
1015 if ( which_token != tokens.size() ) {
1016 if (
get_token( which_token + 1, tokens ) ==
"LEVEL" ) {
1022 std::stringstream err_msg;
1023 err_msg <<
"Extra rotamer sample level " <<
get_token( which_token, tokens ) <<
" is not in the range [0-" <<
ExtraRotSampleCardinality <<
"] for residue " << resid <<
".";
1029 if ( which_chi_ > 2 && aro_specified_ ) {
1030 std::stringstream err_msg;
1031 err_msg <<
"The token following EX ARO, " <<
get_token( which_chi_token, tokens ) <<
", should be a valid chi-id level, eg a '1' or a '2' for residue " << resid <<
".";
1034 else if ( which_chi_ > 4 ) {
1035 std::stringstream err_msg;
1036 err_msg <<
"The given chi-id, '" <<
get_token( which_chi_token, tokens ) <<
"' must either be an integer [1-4] or 'ARO' for residue " << resid <<
".";
1048 if ( which_chi_ == 1 ) {
1049 if ( aro_specified_ ) {
1054 }
else if ( which_chi_ == 2 ) {
1055 if ( aro_specified_ ) {
1060 }
else if ( which_chi_ == 3 ) {
1062 }
else if ( which_chi_ == 4 ) {
1076 assert(
get_token( which_token, tokens ) == name() );
1078 nc_to_include_ =
get_token( which_token, tokens );
1090 if ( residue_set.
has_name( nc_to_include_ )){
1093 std::stringstream err_msg;
1094 err_msg <<
"Unable to add non-canonical amino acid " << nc_to_include_ <<
" because it is not in the ResidueTypeSet for residue " << resid <<
".";
1108 assert(
get_token( which_token, tokens ) == name() );
1113 std::istringstream ex_cutoff_ss(
get_token( which_token, tokens ) );
1115 if (( ex_cutoff_ss >> ex_cutoff_ ).fail() ) {
1116 std::stringstream err_msg;
1117 err_msg <<
"The leve given for EX_CUTOFF, " <<
get_token( which_token-1, tokens) <<
", must be an integer in the range [0-18] where 18 is the default for residue " << resid <<
".";
1142 assert(
get_token( which_token, tokens ) == name() );
1164 assert(
get_token( which_token, tokens ) == name() );
1186 assert(
get_token( which_token, tokens ) == name() );
1209 assert(
get_token( which_token, tokens ) == name() );
1211 if ( which_token == tokens.size() ) {
1212 std::stringstream err_msg;
1213 err_msg <<
"TARGET must be followed by a character or string that identifies a target type. Use '_' if no target type is desired; for residue " << resid <<
".";
1217 argstring_ =
get_token( which_token, tokens );
1226 using namespace chemical;
1232 if ( argstring_.size() == 1 ) {
1233 char letter( argstring_[0] );
1234 if ( letter ==
'_' ) {
return; }
1238 std::stringstream err_msg;
1239 err_msg <<
"Unknown one-letter code '"<< letter <<
"' for TARGET command for residue " << resid <<
".";
1243 else rtask.target_type( argstring_ );
1256 assert(
get_token( which_token, tokens ) == name() );
1279 assert( tokens[ which_token ] == name() );
1297 std::map< std::string, ResfileCommandOP >
1300 using namespace std;
1302 map< string, ResfileCommandOP > command_map;
1332 return get_token( which_token, tokens )[ 0 ] ==
'#';
1349 parse_resfile(pose, the_task, basic::options::option[basic::options::OptionKeys::packing::resfile].value().
at(1));
1361 utility::io::izstream file( filename );
1363 TR <<
"File:" << filename <<
" not found!\n";
1364 utility_exit_with_message(
"Cannot open file " + filename );
1368 utility::slurp( file, resfile );
1372 if (basic::options::option[ basic::options::OptionKeys::run::interactive ].user()){
1394 using namespace std;
1395 istringstream resfile(resfile_string);
1398 for (
Size ii = 1; ii <= pose.total_residue(); ++ii ) {
1400 std::list< ResfileCommandCOP >
const & ii_command_list(
1404 for ( std::list< ResfileCommandCOP >::const_iterator
1405 iter = ii_command_list.begin(), iter_end = ii_command_list.end();
1406 iter != iter_end; ++iter ) {
1407 (*iter)->residue_action( the_task, ii );
1421 const Size which_token,
1423 bool make_upper_case) {
1425 if (which_token > tokens.size() ){
1426 if (which_token == 1){
1427 std::stringstream err_msg;
1428 err_msg <<
"Resfile does not specify anything.";
1431 std::stringstream err_msg;
1432 err_msg <<
"After token " << tokens[ which_token -1 ] <<
" another token is expected.";
1437 if(make_upper_case){
1439 std::transform(token.begin(), token.end(), token.begin(), (
int(*)(
int)) std::toupper);
1450 std::getline( inputstream, input_line );
1452 unsigned int llength = input_line.size();
1453 unsigned int processing = 0;
1454 unsigned int token_start_char = 0;
1456 while ( processing < llength ) {
1457 if ( std::isspace( input_line[ processing ] ) ) {
1458 if ( !( std::isspace(input_line[ token_start_char ] ) ) ) {
1459 std::string token = input_line.substr( token_start_char, processing - token_start_char);
1460 tokens.push_back( token );
1463 token_start_char = processing;
1468 if ( processing != token_start_char ) {
1469 std::string token = input_line.substr( token_start_char, processing - token_start_char + 1 );
1470 tokens.push_back( token );
1483 static bool interactive = basic::options::option[ basic::options::OptionKeys::run::interactive ].value();
1484 TR << message << std::endl;