Rosetta 3.5
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
ResonanceList.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
11 /// @brief
12 /// @detailed
13 ///
14 ///
15 ///
16 /// @author Oliver Lange
17 
18 // Unit Headers
22 
23 
24 // Package Headers
26 #include <core/id/NamedAtomID.hh>
28 
29 // Project Headers
30 #include <core/chemical/AA.hh>
32 
33 // Utility headers
34 #include <ObjexxFCL/format.hh>
35 #include <utility/string_util.hh>
36 // #include <utility/exit.hh>
37 // #include <utility/excn/Exceptions.hh>
38 // #include <utility/vector1.fwd.hh>
39 // #include <utility/pointer/ReferenceCount.hh>
40 // #include <numeric/numeric.functions.hh>
41 // #include <basic/prof.hh>
42 #include <basic/Tracer.hh>
43 // #include <basic/options/option.hh>
44 // #include <basic/options/keys/abinitio.OptionKeys.gen.hh>
45 // #include <basic/options/keys/run.OptionKeys.gen.hh>
46 //#include <basic/options/keys/templates.OptionKeys.gen.hh>
47 
48 //// C++ headers
49 #include <cstdlib>
50 #include <string>
51 #include <deque>
52 #include <sstream>
53 #include <utility/vector1.hh>
54 #include <boost/tokenizer.hpp>
55 
56 
57 static basic::Tracer tr("protocols.noesy_assign.resonances");
58 
59 using core::Real;
60 using namespace core;
61 using namespace basic;
62 //using namespace basic::options;
63 //using namespace basic::options::OptionKeys;
64 
65 namespace protocols {
66 namespace noesy_assign {
67 
68 
69 ResonanceList::ResonanceList( std::string const& sequence ) : sequence_( sequence )
70 {}
71 
73 
74 /// translate sequence information into AA
76  runtime_assert( resi <= sequence_.size() );
78 }
79 
80 
81 /* helper function for 'read_from_stream'
82  each element is first put into a DEQUE such that atoms like methyl-protons can be combined if they are assigned the same frequency.
83  -HB1, HB2 -- > QB
84 
85  example:
86  input:
87  HB1 1.00
88  HB2 1.00
89  CD 13.00
90 
91  output:
92  QB 1.00
93  CD 13.00
94 */
95 void process_last_resonances( std::deque< ResonanceOP >& last_resonances, bool drain=false ) {
96 
97 
98  ResonanceOP first_res = last_resonances.front();
99  last_resonances.pop_front();
100  first_res->combine( last_resonances, drain );
101  last_resonances.push_front( first_res );
102  /*
103  //is this a HB1, HG1 or a 1HG2 type of name ?
104  bool single_char ( first_res->name().size() == 3 );
105 
106  //do we have enough protons for a QQX type of combined atom. (2 methyl groups... )
107  bool double_methyl( last_resonances.size() == 6 );
108 
109  //
110  Size str_cmp_length( 1 );
111 
112  std::string pseudo_letter( "Q" ); //default, single methyl group, proton
113  if ( first_res->name().substr(0,1)=="C" ) pseudo_letter = "C"; //not default, we don't have a proton
114  if ( first_res->name().substr(0,1)=="Q" ) pseudo_letter = "QQ"; //not default, this is a double-methyl...
115  //if the two protons stuffed into the ambiguity queue are, .e.g, QG1 + QG2 --> QQG
116 
117  core::Real intensity_sum( first_res->intensity() );
118  // construct combined atom name, QX, QQX
119  if ( single_char ) { //things like HB1+HB2 or QG1+QG2
120  combine_name=pseudo_letter+first_res->name().substr(1,1);
121  } else if ( double_methyl ) { //-->QQX
122  combine_name=pseudo_letter+pseudo_letter+first_res->name().substr(1,1);
123  } else { // HG11+HG12+HG13 --> QG1
124  combine_name=pseudo_letter+first_res->name().substr(1,2);
125  str_cmp_length=2;
126  }
127 
128  //now figure out, how many atoms can be combined...
129  Size limit( drain ? 0 : 1 ); //should we go to the very end, or leave last atom behind...
130  while( last_resonances.size() > limit ) {//check others
131  if ( first_res->name().substr( 1, str_cmp_length ) == last_resonances.front()->name().substr( 1, str_cmp_length ) ) {
132  intensity_sum+=last_resonances.front()->intensity();
133  last_resonances.pop_front();
134  } else { //could not combine...
135  combine_name = first_res->name();
136  break;
137  }
138  } //now replace front of deque with the combined atom
139  last_resonances.push_front( new Resonance( first_res->label(), first_res->freq(), first_res->error(), core::id::NamedAtomID( combine_name, first_res->resid() ), first_res->aa(), intensity_sum ) );
140  */
141 }
142 
143 void ResonanceList::read_from_stream( std::istream& is ) {
144  using namespace core::chemical; //for AA
146  std::string line;
147  std::deque< ResonanceOP > last_resonances;
148  while( getline( is, line ) ) {
149  core::Size label;
150  core::Real freq;
151  core::Real error;
152  std::string name;
153  core::Size resn;
154  AA aa;
155  std::istringstream line_stream( line );
156 
157  //read from stream...
158  tr.Trace << "read line: " << line << std::endl;
159  line_stream >> label >> freq >> error >> name;
160  if ( params.ignore_resonancefile_tolerances_ ) error = 0.0;
161 
162  //check for stream-error
163  if ( !line_stream.good() ) {
164  tr.Info << "ignore line : " << line << std::endl;
165  continue; //ignore weird lines
166  }
167 
168  if ( name=="" ) break;//got an empty line at end of file ?
169 
170  //read optional fields
171  line_stream >> resn;
172  std::string aa_name;
173  line_stream >> aa_name;
174 
175  //process optional fields...
176  if ( line_stream.good() ) { //optional field present?
177  if ( aa_name.size() == 1 ) {
178  aa = aa_from_oneletter_code( aa_name[ 0 ] );
179  } else if ( aa_name.size() == 3 ) {
180  aa = aa_from_name( aa_name );
181  } else {
182  throw utility::excn::EXCN_BadInput( "did not recognize aminoacid: " + aa_name);
183  }
184  if ( sequence_.size() < resn ) {
185  while ( sequence_.size() < resn-1 ) sequence_.push_back('X');
186  sequence_[ resn-1 ]=oneletter_code_from_aa( aa );
187  } else if ( sequence_[ resn-1 ]!=oneletter_code_from_aa( aa ) ) {
188  tr.Warning << "sequence mismatch!! check your data: found " << name_from_aa( aa ) << " in line " << line
189  << " which does not match " << sequence_[ resn-1 ] << "\n" << sequence_ << std::endl;
190  }
191  } else { //optional field was not present... use the pre-supplied fasta-sequence
192  aa = aa_from_resid( resn );
193  }
194  line_stream >> aa_name; //1-letter
195 
196  Real intensity( 1.0 );
197  line_stream >> intensity;
198  if ( !line_stream ) { //option field intensity present ?
199  intensity=1.0;
200  }
201 
202  std::string fl_tag;
203  line_stream >> fl_tag;
204  typedef std::set< core::Size > FloatList;
205  FloatList floats;
206  if ( line_stream ) {
207  if ( fl_tag[0]!='#' && fl_tag[0]!='[' ) {
208  throw utility::excn::EXCN_BadInput( "did not recognize item " +fl_tag + " in line " + line );
209  } else {
210  std::stringstream float_info;
211  fl_tag[0]=' ';
212  bool closed( false );
213  if ( fl_tag[ fl_tag.size()-1 ]==']' ) {
214  fl_tag.replace( fl_tag.size()-1, 1, " ");
215  closed = true;
216  }
217  float_info << fl_tag;
218  while ( line_stream && !closed ) {
219  line_stream >> fl_tag;
220  if ( fl_tag[ fl_tag.size()-1 ]==']' ) {
221  fl_tag.replace( fl_tag.size()-1, 1, " ");
222  closed = true;
223  }
224  float_info << fl_tag;
225  }
226  if ( !closed ) {
227  throw utility::excn::EXCN_BadInput( "expect closing ] in line " + line );
228  }
229  char cstr[100];
230  while ( float_info.getline(cstr, 50, ',' ) ) {
231  tr.Debug << "add " << cstr << " to float group for resonance " << label << std::endl;
232  floats.insert( utility::string2int( cstr ));
233  tr.Debug << floats.size() << std::endl;
234  }
235  }
236  }
237 
238 
239  // replace some names...
240  if ( name == "HN" ) name ="H";
241  if ( aa == aa_leu && name == "HD1" ) name = "QD1";
242  if ( aa == aa_leu && name == "HD2" ) name = "QD2";
243  if ( aa == aa_val && name == "HG1" ) name = "QG1";
244  if ( aa == aa_val && name == "HG2" ) name = "QG2";
245  if ( aa == aa_thr && name == "HG2" ) name = "QG2";
246  if ( aa == aa_ala && name == "HB" ) name = "QB";
247  if ( aa == aa_gly && name == "HA" ) name = "QA";
248  if ( aa == aa_ile && name == "HG1" ) name = "QG1";
249  if ( aa == aa_ile && name == "HG2" ) name = "QG2";
250  if ( aa == aa_ile && name == "HD1" ) name = "QD1";
251 
252  ResonanceOP save_resonance( new Resonance( label, freq, error, core::id::NamedAtomID( name, resn ), aa, intensity ) );
253  if ( floats.size() ) {
254  save_resonance = new FloatingResonance( *save_resonance, floats, this );
255  }
256 
257  // before assigning to Resonance List put it in DEQUE (push_back), maybe it will get combined with next resonance...
258  last_resonances.push_back( save_resonance );
259  if ( freq != last_resonances.front()->freq() ) { ///if we have just read a new frequency we need to finalize what is in the DEQUE
260  if ( last_resonances.size() > 2 ) process_last_resonances( last_resonances ); //just 2 --> 1 old freq and 1 new freq
261  map_[ last_resonances.front()->label() ] = last_resonances.front(); ///assign most forward value in our DEQUE
262  last_resonances.pop_front(); ///remove the just-assigned value
263  }
264  }
265 
266  //still unprocessed data in DEQUE ?
267  if ( last_resonances.size() > 1 ) process_last_resonances( last_resonances, true /*drain*/ );
268  map_[ last_resonances.front()->label() ]= last_resonances.front();
269 
270  //ASSERT: we have captured everything...
271  runtime_assert( last_resonances.size() == 1 );
272 
273  ///no problems ?
274  if ( is.fail() && is.eof() && is.bad() ) {
275  tr.Error << "[ERROR WHILE READING]" << std::endl;
276  }
277 
278  //post-process input...
280 
281  //fix intensities...
282  if ( params.ignore_resonancefile_intensities_ ) {
283  for ( ResonanceIDs::const_iterator it = map_.begin(); it != map_.end(); ++it ) {
286  parse_NMR_name( it->second->name(), it->second->resid(), it->second->aa(), atoms );
287  it->second->set_intensity( atoms.size() );
288  }
289  }
290 
291  //fix floating assignments...
292  for ( ResonanceIDs::const_iterator it = map_.begin(); it != map_.end(); ++it ) {
293 
294  }
295 
296 }
297 
298 ///@brief write ResonanceList to stream
299 void ResonanceList::write_to_stream( std::ostream& os ) const {
300  for ( ResonanceIDs::const_iterator it = map_.begin(); it != map_.end(); ++it ) {
301  runtime_assert( it->first == it->second->label() );
302  if ( sequence_.size() ) {
303  using namespace core::chemical; //for AA
304  AA aa( aa_from_resid( it->second->resid() ) );
305  it->second->write_to_stream( os, aa );
306  } else {
307  it->second->write_to_stream( os );
308  }
309  os << std::endl;
310  }
311 }
312 
313 ///@brief write ResonanceList in TALOS format
314 void ResonanceList::write_talos_format( std::ostream& os, bool backbone_only ) const {
315  if ( sequence_.size() == 0 ) {
316  utility_exit_with_message( "sequence information required to write TALOS format -- use -in:file:fasta" );
317  }
318 
319  //write sequence section
320  Size const TALOS_SEQ_LINE_LEN( 50 );
321  Size const TALOS_SEQ_BLCK_SIZE( 10 );
322  for ( Size ct=0; ct<sequence_.size(); ct++ ) {
323  if ( ct % TALOS_SEQ_LINE_LEN == 0 && ct > 1 ) os <<"\n";
324  if ( ct % TALOS_SEQ_LINE_LEN == 0 ) os << "DATA SEQUENCE";
325  if ( ct % TALOS_SEQ_BLCK_SIZE == 0 ) os << " ";
326  os << sequence_[ ct ];
327  }
328 
329  ///write format section
330  os << "\n\n";
331  os << "VARS RESID RESNAME ATOMNAME SHIFT\n";
332  os << "FORMAT %4d %1s %4s %8.3f\n";
333  os << "\n";
334 
335 
336  ///write resonances
337  for ( ResonanceIDs::const_iterator it = map_.begin(); it != map_.end(); ++it ) {
338  runtime_assert( it->first == it->second->label() );
339  if ( sequence_.size() < it->second->resid() ) {
340  tr.Error << " no sequence information for residue " << it->second->resid() << std::endl;
341  utility_exit_with_message( "sequence information required for all residues to write TALOS format -- use -in:file:fasta" );
342  }
343  using namespace core::chemical; //for AA
344  std::string atom( it->second->name() );
345 
346  //are we backbone
347  bool const is_backbone( //backbone im Sinne von SPARTA
348  atom=="H" || atom=="HN" ||
349  atom=="CA" || atom=="CB" ||
350  atom=="N" ||
351  atom=="1HA" || atom=="2HA" || atom=="3HA" );
352  //write individual atom
353  if ( is_backbone || !backbone_only ) {
354  if ( atom=="1HA" ) atom="HA3";
355  if ( atom=="2HA" ) atom="HA2";
356  if ( atom=="3HA" ) atom="HA1";
357  AA aa( aa_from_resid( it->second->resid() ) );
358  os << ObjexxFCL::fmt::RJ( 5, it->second->resid() ) << " ";
359  os << oneletter_code_from_aa( aa ) << " ";
360  os << ObjexxFCL::fmt::RJ( 3, atom=="H" ? "HN" : atom ) << " ";
361  os << ObjexxFCL::fmt::F( 7, 3, it->second->freq() ) << std::endl;
362  }
363  }
364  os << std::endl;
365 }
366 
367 
368 ///retrieve Resonance --- throws EXCN_UnknonwResonance if atom not found
370  ResidueMap::const_iterator it_res( by_resid_.find( atom.rsd() ) );
371  if ( it_res != by_resid_.end() ) {
372  Resonances const& reso_list( it_res->second );
373  for ( Resonances::const_iterator it = reso_list.begin(); it != reso_list.end(); ++it ) {
374  if ( (*it)->atom() == atom ) return **it;
375  }
376  }
377  throw EXCN_UnknownResonance( atom, "can't find atom ");
378  return *(map_.begin()->second); //to make compiler happy
379 }
380 
381 ///retrieve Resonance --- throws EXCN_UnknonwResonance if atom not found
383  ResonanceIDs::const_iterator iter = map_.find( key );
384  if ( iter == map_.end() ) {
385  throw EXCN_UnknownResonance( id::BOGUS_NAMED_ATOM_ID, "can't find resonance " + ObjexxFCL::string_of( key ) );
386  }
387  return *(iter->second);
388 }
389 
390 ///create map with all resonances sorted by residue number
392  by_resid_.clear();
393  for ( ResonanceIDs::const_iterator it = map_.begin(); it != map_.end(); ++it ) {
394  runtime_assert( it->first == it->second->label() );
395  by_resid_[ it->second->resid() ].push_back( it->second );
396  }
397 }
398 
399 ///retrieve list of Resonance at certain residue --- throws EXCN_UnknonwResonance if residue number not found
401  ResidueMap::const_iterator it_res( by_resid_.find( resid ) );
402  if ( it_res != by_resid_.end() ) {
403  return it_res->second;
404  }
405  throw EXCN_UnknownResonance( id::BOGUS_NAMED_ATOM_ID, "can't find resonance with residue " + ObjexxFCL::string_of( resid ) );
406  return by_resid_.begin()->second; //to make compile happy
407 }
408 
409 
411  return by_resid_.find( resid ) != by_resid_.end();
412 }
413 
414 }
415 }