Rosetta 3.5
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
RNA_ChemicalShiftPotential.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 core/scoring/rna/chemical_shift/RNA_ChemicalShiftPotential.cc
11 /// @brief The real workhorse behind RNA_ChemicalShiftEnergy.cc
12 /// @author Parin Sripakdeevong (sripakpa@stanford.edu)
13 
14 
15 // Unit headers
17 
18 
19 // Project headers
20 #include <core/pose/Pose.hh>
23 
24 
25 // Utility headers
26 
27 //Auto Headers
28 #include <core/id/AtomID.hh>
29 
30 ////////////////////////////////////////////////////////
31 #include <basic/Tracer.hh>
32 ////////////////////////////////////////////////////////
33 #include <basic/options/option.hh>
34 #include <basic/options/keys/score.OptionKeys.gen.hh>
35 //#include <core/io/database/open.hh>
36 #include <utility/file/file_sys_util.hh>
37 #include <utility/io/izstream.hh>
38 #include <ObjexxFCL/format.hh>
42 #include <math.h>
43 #include <numeric/xyzVector.hh>
47 
48 
49 
50 // C++
51 
52 static basic::Tracer TR("core.scoring.rna.chemical_shift.RNA_ChemicalShiftPotential");
53 
54 namespace core {
55 namespace scoring {
56 namespace rna {
57 namespace chemical_shift {
58 
59 
60 
61  /// c-tor
63  rna_cs_params_( RNA_CS_parameters() ),
64  verbose_(true),
65  include_ring_current_effect_(true),
66  include_magnetic_anisotropy_effect_(true),
67  total_exp_chemical_shift_data_points_( 0 )
68  {
69 
71  std::cout << "include_ring_current_effect_= true " << std::endl;
72  }else{
73  std::cout << "include_ring_current_effect_= false " << std::endl;
74  }
75 
77  std::cout << "include_magnetic_anisotropy_effect_= true " << std::endl;
78  }else{
79  std::cout << "include_magnetic_anisotropy_effect_= false " << std::endl;
80  }
81 
82  if( basic::options::option[ basic::options::OptionKeys::score::rna_chemical_shift_exp_data].user()==false ){
83  utility_exit_with_message("User need to pass in score:rna_chemical_shift_exp_data");
84  }
85 
86  std::string const exp_CS_data_filename=basic::options::option[ basic::options::OptionKeys::score::rna_chemical_shift_exp_data]();
87 
88  utility::vector1< core::Size > include_res_list;
89 
90  if( basic::options::option[ basic::options::OptionKeys::score::rna_chemical_shift_include_res].user()){
91  include_res_list=basic::options::option[ basic::options::OptionKeys::score::rna_chemical_shift_include_res]();
92  }else{
93  TR << "User did not pass in score:rna_chemical_shift_include_res, including all residue!" << std::endl;
94  if(include_res_list.size()!=0) utility_exit_with_message("User did not pass in score:rna_chemical_shift_include_res option but include_res_list.size()!=0!");
95  }
96 
97  if( basic::options::option[ basic::options::OptionKeys::score::rna_chemical_shift_H5_prime_mode].user()){
98  H5_prime_mode_=basic::options::option[ basic::options::OptionKeys::score::rna_chemical_shift_H5_prime_mode]();
99  TR << "Using user-specified H5_prime_mode_= " << H5_prime_mode_ << std::endl;
100  }else{
101  H5_prime_mode_="LEAST_SQUARE_IGNORE_DUPLICATE"; //DEFAULT!
102  TR << "Using default H5_prime_mode_= " << H5_prime_mode_ << std::endl;
103  }
104 
105 
107 
108  proton_entry_list.push_back(string_list("H1*"));
109  proton_entry_list.push_back(string_list("1H2*"));
110  proton_entry_list.push_back(string_list("H3*"));
111  proton_entry_list.push_back(string_list("H4*"));
112 
113  if(H5_prime_mode_=="UNIQUE"){
114  proton_entry_list.push_back(string_list("1H5*"));
115  proton_entry_list.push_back(string_list("2H5*"));
116 
117  }else if(H5_prime_mode_=="LEAST_SQUARE" or H5_prime_mode_=="LEAST_SQUARE_IGNORE_DUPLICATE"){
118  proton_entry_list.push_back(string_list("1H5*", "2H5*"));
119 
120  }else{
121  utility_exit_with_message("Invalid H5_prime_mode_ (" + H5_prime_mode_ + ")!");
122  }
123 
124  /////Non-polar base protons/////
125  proton_entry_list.push_back(string_list("H2"));
126  proton_entry_list.push_back(string_list("H5"));
127  proton_entry_list.push_back(string_list("H6"));
128  proton_entry_list.push_back(string_list("H8"));
129 
130 
131  import_exp_chemical_shift_data(exp_CS_data_filename, include_res_list, proton_entry_list);
132 
133  }
134 
135 
136 
137  /////////////////////////////////////////////////////////////////////////////
138  // scoring
139  /////////////////////////////////////////////////////////////////////////////
141  get_res_aa_from_BASE_name(std::string BASE_name, std::string const text_line){
142 
144 
145  if(BASE_name=="G"){
146 
147  res_aa=chemical::na_rgu;
148 
149  }else if(BASE_name=="A"){
150 
151  res_aa=chemical::na_rad;
152 
153  }else if(BASE_name=="C"){
154 
155  res_aa=chemical::na_rcy;
156 
157  }else if(BASE_name=="U"){
158 
159  res_aa=chemical::na_ura;
160 
161  }else{
162  utility_exit_with_message("Invalid BASE_name (" +BASE_name+ ") | line= (" +text_line+")");
163  }
164 
165  return res_aa;
166 
167  }
168 
169  /////////////////////////////////////////////////////////////////////////////
171  remove_whitespaces(std::string const in_atom_name){
172 
173  std::string out_atom_name="";
174 
175  for(Size n=0; n<in_atom_name.size(); n++){
176 
177  if(in_atom_name[n]!=' ') out_atom_name+=in_atom_name[n];
178 
179  }
180 
181  return out_atom_name;
182  }
183 
184 
185  /////////////////////////////////////////////////////////////////////////////
186  bool
187  is_polar_hydrogen(std::string const input_atom_name){
188 
189  if(input_atom_name=="2HO*" || input_atom_name=="HO2'") return true;
190 
191  if(input_atom_name=="1H2" || input_atom_name=="H21") return true;
192 
193  if(input_atom_name=="2H2" || input_atom_name=="H22") return true;
194 
195  if(input_atom_name=="1H4" || input_atom_name=="H41") return true;
196 
197  if(input_atom_name=="2H4" || input_atom_name=="H42") return true;
198 
199  if(input_atom_name=="1H6" || input_atom_name=="H61") return true;
200 
201  if(input_atom_name=="2H6" || input_atom_name=="H62") return true;
202 
203  if(input_atom_name=="H1") return true;
204 
205  if(input_atom_name=="H3") return true;
206 
207  if(input_atom_name=="HO3'") return true; //Can occur at 3' ends of RNA's chain. This is not part of the standard rosetta atom-set
208 
209  if(input_atom_name=="HO5'") return true; //Can occur at 5' ends of RNA's chain. this is not part of the standard rosetta atom-set
210 
211  return false;
212 
213  }
214 
215  /////////////////////////////////////////////////////////////////////////////
217  get_rosetta_hatom_name(std::string const input_atom_name, std::string const text_line, utility::vector1< std::string > const & flat_proton_entry_list){
218 
219  using namespace ObjexxFCL;
220 
221  std::string rosetta_atom_name="";
222 
223  //Assume that input_atom_name is a non_polar hydrogen atom! Other atoms should be filtered before reaching this point!
224  if(input_atom_name=="H1'"){
225  rosetta_atom_name="H1*";
226 
227  }else if(input_atom_name=="H2'"){
228  rosetta_atom_name="1H2*";
229 
230  }else if(input_atom_name=="H3'"){
231  rosetta_atom_name="H3*";
232 
233  }else if(input_atom_name=="H4'"){
234  rosetta_atom_name="H4*";
235 
236  }else if(input_atom_name=="H5'"){
237  rosetta_atom_name="1H5*";
238 
239  }else if(input_atom_name=="H5''"){
240  rosetta_atom_name="2H5*";
241  }else{
242  rosetta_atom_name=input_atom_name;
243  }
244 
245  Size num_matching_atom_name=0;
246 
247  for(Size ii=1; ii<=flat_proton_entry_list.size(); ii++){
248  if(rosetta_atom_name==flat_proton_entry_list[ii]) num_matching_atom_name++;
249  }
250 
251  if(num_matching_atom_name!=1){
252  std::cout << "ERROR: num_matching_atom_name=" << num_matching_atom_name << std::endl;
253  std::cout << "ERROR: input_atom_name=" << input_atom_name << std::endl;
254  std::cout << "ERROR: rosetta_atom_name=" << rosetta_atom_name << std::endl;
255  utility_exit_with_message("num_matching_atom_name!=1 for input_atom_name (" + input_atom_name + ") | text_line (" + text_line + ")");
256  }
257 
258  return rosetta_atom_name;
259 
260  }
261 
262 
263  /////////////////////////////////////////////////////////////////////////////
264  void
265  print_chemical_shift_data(std::string prestring, ChemicalShiftData const & CS_data, bool const print_data_line){
266 
267  std::cout << prestring << "seq_num=" << std::setw(3) << CS_data.seq_num;
268  std::cout << " | res_aa=" << std::setw(3) << name_from_aa(CS_data.res_aa);
269  std::cout << " | atom_name=" << std::setw(5) << CS_data.atom_name;
270  std::cout << " | realatomdata_index=" << std::setw(3) << CS_data.realatomdata_index;
271  std::cout << " | exp_shift=" << std::setw(8) << CS_data.exp_shift;
272  if(print_data_line) std::cout << " | data_line=" << CS_data.data_line;
273  std::cout << std::endl;
274 
275  }
276 
277  ////////////////////////////////copied from protocols/swa/rna/StepWiseRNA_Util.cc/////////////////////////////
278  core::Size
279  string_to_int(std::string const input_string){
280 
281  Size int_of_string; //misnomer
282  std::stringstream ss (std::stringstream::in | std::stringstream::out);
283 
284  ss << input_string;
285 
286  if(ss.fail()) utility_exit_with_message("In string_to_real(): ss.fail() for ss << input_string | string ("+input_string+")");
287 
288  ss >> int_of_string;
289 
290  if(ss.fail()) utility_exit_with_message("In string_to_real(): ss.fail() for ss >> int_of_string | string ("+input_string+")");
291 
292  return int_of_string;
293  }
294 
295  ////////////////////////////////copied from protocols/swa/rna/StepWiseRNA_Util.cc/////////////////////////////
296  core::Real
297  string_to_real(std::string const input_string){
298 
299  Real real_of_string;
300  std::stringstream ss (std::stringstream::in | std::stringstream::out);
301 
302  ss << input_string;
303 
304  if(ss.fail()) utility_exit_with_message("In string_to_real(): ss.fail() for ss << input_string | string ("+input_string+")");
305 
306  ss >> real_of_string;
307 
308  if(ss.fail()) utility_exit_with_message("In string_to_real(): ss.fail() for ss >> real_of_string | string ("+input_string+")");
309 
310  return real_of_string;
311 
312  }
313 
314  ////////////////////////////////copied from protocols/swa/rna/StepWiseRNA_Util.cc/////////////////////////////
315  bool
316  Contain_seq_num(Size const & seq_num, utility::vector1< core::Size > const & residue_list){
317  for(Size j=1; j<=residue_list.size(); j++){
318  if(seq_num==residue_list[j]) {
319  return true;
320  }
321  }
322  return false;
323  }
324 
325  /////////////////////////////////////////////////////////////////////////////
326 
328  filter_chem_shift_data_list(utility::vector1 < ChemicalShiftData > const & flat_EXP_chem_shift_data_list, core::Size const seq_num, utility::vector1 < std::string > const & proton_entry){
329 
330  utility::vector1 < ChemicalShiftData > filtered_CS_data_list;
331 
332  for(Size ii=1; ii<=flat_EXP_chem_shift_data_list.size(); ii++){
333 
334  ChemicalShiftData const & CS_data=flat_EXP_chem_shift_data_list[ii];
335 
336  if(CS_data.seq_num!=seq_num) continue;
337 
338  Size num_matching_atom_name=0;
339 
340  for(Size jj=1; jj<=proton_entry.size(); jj++){
341  if(proton_entry[jj]==CS_data.atom_name) num_matching_atom_name++;
342  }
343 
344  if(num_matching_atom_name>1) utility_exit_with_message("num_matching_atom_name>1!");
345 
346  if(num_matching_atom_name==1) filtered_CS_data_list.push_back(CS_data);
347 
348  }
349 
350  if(filtered_CS_data_list.size()>0){
351 
352  if(filtered_CS_data_list.size()!=proton_entry.size()){
353  std::cout << "ERROR: filtered_CS_data_list.size()>0 at seq_num=" << seq_num << " proton_entry: ";
354  for(Size jj=1; jj<=proton_entry.size(); jj++){
355  std::cout << "# " << jj << " :" << proton_entry[jj] <<std::endl;
356  }
357  std::cout << "ERROR: filtered_CS_data_list: " << std::endl;
358  for(Size jj=1; jj<=filtered_CS_data_list.size(); jj++){
359  print_chemical_shift_data("#" + ObjexxFCL::lead_zero_string_of(jj, 3) + " :", filtered_CS_data_list[jj], true );
360  }
361 
362  utility_exit_with_message("filtered_CS_data_list.size()>0 BUT filtered_CS_data_list.size()!=proton_entry.size()!");
363  }
364  }
365 
366  return filtered_CS_data_list;
367 
368  }
369 
370  /////////////////////////////////////////////////////////////////////////////
371  Size
373 
374  if(total_exp_chemical_shift_data_points_==0) utility_exit_with_message("total_exp_chemical_shift_data_points_==0!");
375 
377 
378  }
379 
380  /////////////////////////////////////////////////////////////////////////////
381 
384 
386 
387  string_list.push_back(string_one);
388 
389  return string_list;
390  }
391 
392  /////////////////////////////////////////////////////////////////////////////
393 
395  RNA_ChemicalShiftPotential::string_list(std::string const string_one, const std::string string_two) const{
396 
398 
399  string_list.push_back(string_one);
400  string_list.push_back(string_two);
401 
402  return string_list;
403  }
404 
405 
406  /////////////////////////////////////////////////////////////////////////////
407  Size
409 
410  using namespace ObjexxFCL;
411 
412  std::string const atom_name=remove_whitespaces(in_atom_name);
413 
415 
416  Size const maxatoms=rna_cs_rsd_params.get_atomnames_size();
417 
418  Size num_matching_atom_name=0;
419 
420  Size realatomdata_index=0;
421 
422  for(Size count=1; count<=maxatoms; count++){
423 
424  if(rna_cs_rsd_params.get_atomname(count)==atom_name){
425  num_matching_atom_name++;
426  realatomdata_index=count;
427  }
428 
429  }
430 
431  if(num_matching_atom_name!=1) utility_exit_with_message("num_matching_atom_name=("+ string_of(num_matching_atom_name)+")!=1 | atom_name ("+ atom_name+")!");
432 
433  return realatomdata_index;
434 
435  }
436 
437 
438  /////////////////////////////////////////////////////////////////////////////
439  void
441 
442  using namespace ObjexxFCL;
443 
444  //OK this is another layer of consistency check////
445  if(CS_data.atom_name=="H8"){
446  if( CS_data.res_aa!=chemical::na_rgu && CS_data.res_aa!=chemical::na_rad){
447  utility_exit_with_message("CS_data.atom_name==\"H8\" but CS_data.res_aa!=na_rgu && CS_data.res_aa!=na_rad!");
448  }
449  }
450 
451  if(CS_data.atom_name=="H5" || CS_data.atom_name=="H6"){
452  if( CS_data.res_aa!=chemical::na_rcy && CS_data.res_aa!=chemical::na_ura ){
453  utility_exit_with_message("CS_data.atom_name==\"" +CS_data.atom_name + "\" but CS_data.res_aa!=na_rcy && CS_data.res_aa!=na_ura!");
454  }
455  }
456 
457  if(CS_data.atom_name=="H2" ){
458  if( CS_data.res_aa!=chemical::na_rad ) utility_exit_with_message("CS_data.atom_name==\"H2\" but CS_data.res_aa!=na_rad!");
459  }
460 
461 
462  ////////////////////////////This is imino/amino (polar) proton [not current in use!]////////////////////////////////////////
463  if(CS_data.atom_name=="H1"){ //Still need to account for the possibility of protonated Adenosine at N1 pos!
464  if( CS_data.res_aa!=chemical::na_rgu ) utility_exit_with_message("CS_data.atom_name==\"H1\" but CS_data.res_aa!=na_rgu!");
465  }
466 
467  if(CS_data.atom_name=="H3"){ //Still need to account for the possibility of protonated Cytosine at N3 pos!
468  if( CS_data.res_aa!=chemical::na_ura) utility_exit_with_message("CS_data.atom_name==\"H3\" but CS_data.res_aa!=na_ura!");
469  }
470 
471  if(CS_data.atom_name=="1H2" || CS_data.atom_name=="2H2"){
472  if( CS_data.res_aa!=chemical::na_rgu){
473  utility_exit_with_message("CS_data.atom_name==\"" + CS_data.atom_name + "\" but CS_data.res_aa!=na_rgu!");
474  }
475  }
476 
477  if(CS_data.atom_name=="1H4" || CS_data.atom_name=="2H4"){
478  if( CS_data.res_aa!=chemical::na_rcy){
479  utility_exit_with_message("CS_data.atom_name==\"" + CS_data.atom_name + "\" but CS_data.res_aa!=na_rcy!");
480  }
481  }
482 
483  if(CS_data.atom_name=="1H6" || CS_data.atom_name=="2H6"){
484  if( CS_data.res_aa!=chemical::na_rad){
485  utility_exit_with_message("CS_data.atom_name==\"" + CS_data.atom_name + "\" but CS_data.res_aa!=na_rad!");
486  }
487  }
488  ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
489 
490 
492 
493  if(rna_cs_rsd_params.atom_data(CS_data.realatomdata_index, csca)==false){
494  print_chemical_shift_data("ERROR CS_data:", CS_data, true);
495  utility_exit_with_message("CS_data.realatomdata_index ("+string_of(CS_data.realatomdata_index)+") | CS_data.atom_name ("+ CS_data.atom_name+") is not a calc_chem_shift_atom!");
496  }
497 
498  }
499 
500 
501 
502  /////////////////////////////////////////////////////////////////////////////
503  bool
505 
506  using namespace ObjexxFCL;
507 
508  std::string const atom_name=remove_whitespaces(rsd.atom_name(atomno));
509 
511 
512  Size const realatomdata_index=get_realatomdata_index(atom_name, rsd.aa());
513 
514  bool const Is_MA_source_atom= ( dround( rna_cs_rsd_params.atom_data(realatomdata_index, maca) ) == 1 );
515 
516  return Is_MA_source_atom;
517 
518  }
519 
520  /////////////////////////////////////////////////////////////////////////////
521  bool
523 
524  using namespace ObjexxFCL;
525 
526  Size num_matching_CS_data=0;
527 
528  Size const seq_num=rsd.seqpos();
529 
530  std::string const atom_name=remove_whitespaces(rsd.atom_name(atomno));
531 
532  for(Size outer_data_ID=1; outer_data_ID<=EXP_chem_shift_data_list_.size(); outer_data_ID++){
533 
534  for(Size inner_data_ID=1; inner_data_ID<=EXP_chem_shift_data_list_[outer_data_ID].size(); inner_data_ID++){
535 
536  ChemicalShiftData const & CS_data= EXP_chem_shift_data_list_[outer_data_ID][inner_data_ID];
537 
538  if(CS_data.seq_num!=seq_num) continue;
539 
540  if(CS_data.atom_name!=atom_name) continue;
541 
542  num_matching_CS_data++;
543 
544  }
545  }
546 
547  if(num_matching_CS_data>1) utility_exit_with_message("num_matching_CS_data>1 for seq_num= ("+string_of(seq_num)+") | atom_name= ("+atom_name+")");
548 
549  return (num_matching_CS_data==1);
550 
551  }
552 
553 
554  /////////////////////////////////////////////////////////////////////////////
557 
558  using namespace ObjexxFCL;
559 
560  Size num_matching_CS_data=0;
561 
562  Size matching_outer_data_ID=0;
563 
564  std::string const atom_name= remove_whitespaces(in_atom_name);
565 
566  for(Size outer_data_ID=1; outer_data_ID<=EXP_chem_shift_data_list_.size(); outer_data_ID++){
567 
568  for(Size inner_data_ID=1; inner_data_ID<=EXP_chem_shift_data_list_[outer_data_ID].size(); inner_data_ID++){
569 
570  ChemicalShiftData const & CS_data= EXP_chem_shift_data_list_[outer_data_ID][inner_data_ID];
571 
572  if(CS_data.seq_num!=seq_num) continue;
573 
574  if(CS_data.atom_name!=atom_name) continue;
575 
576  num_matching_CS_data++;
577 
578  matching_outer_data_ID=outer_data_ID;
579 
580  }
581 
582  }
583 
584  if(num_matching_CS_data!=1) utility_exit_with_message("num_matching_CS_data!=1 for seq_num= ("+string_of(seq_num)+") | atom_name= ("+atom_name+")");
585 
586  return EXP_chem_shift_data_list_[matching_outer_data_ID];
587 
588  }
589 
590  /////////////////////////////////////////////////////////////////////////////
591  void
593  utility::vector1 < Size > include_res_list,
594  utility::vector1< utility::vector1< std::string > > const & proton_entry_list){
595 
596  using namespace ObjexxFCL;
597 
598  //////////////////////////////////////////////////////////////////////
599 
600  if(utility::file::file_exists( exp_CS_data_filename )==false){
601  utility_exit_with_message( "exp_CS_data_filename " + exp_CS_data_filename + " doesn't exist!" );
602  }
603 
604  utility::io::izstream data( exp_CS_data_filename );
605  if ( !data.good() ){
606  utility_exit_with_message( "Unable to open exp_CS_data_file: "+exp_CS_data_filename);
607  }else{
608  std::cout << "Successfully opened open exp_CS_data_file: \"" << exp_CS_data_filename<< "\" !" << std::endl;
609  }
610  //////////////////////////////////////////////////////////////////////
611  utility::vector1 < ChemicalShiftData > flat_EXP_chem_shift_data_list;
612 
613  utility::vector1< std::string > flat_proton_entry_list;
614  for(Size ii=1; ii<=proton_entry_list.size(); ii++){
615  for(Size jj=1; jj<=proton_entry_list[ii].size(); jj++){
616  flat_proton_entry_list.push_back(proton_entry_list[ii][jj]);
617  }
618  }
619 
620  //////////////////////////////////////////////////////////////////////
621 
622  std::string text_line;
623 
624  Size max_seq_num=0;
625 
626  while( getline( data, text_line ) ){
627 
628  std::istringstream text_stream( text_line );
629 
630  utility::vector1 < std::string > text_line_list;
631 
632  while( true ){
633 
634  std::string str_element;
635 
636  text_stream >> str_element;
637 
638  if(text_stream.fail()) break;
639 
640  text_line_list.push_back(str_element);
641  }
642 
643  if(text_line_list.size()!=9){
644  utility_exit_with_message("text_line_list.size()!=9 for line (" + text_line + ")");
645  }
646 
647  //Consistency_check
648  if(text_line_list[2]!=text_line_list[3]){
649  utility_exit_with_message("text_line_list[2]=("+ text_line_list[2] +")!=("+ text_line_list[3] +")=text_line_list[3]");
650  }
651 
652  Size const seq_num=string_to_int(text_line_list[3]);
653 
654 
655  chemical::AA res_aa=get_res_aa_from_BASE_name(text_line_list[4], text_line);
656 
657  // different member versions of find in the same order as above:
658  std::string const input_atom_name=text_line_list[5];
659 
660  size_t found=input_atom_name.find("H");
661 
662  if(found==std::string::npos){ //Filter out potential carbon, nitrogen and phosphorus chemical_shift line
663  if(false) std::cout << "Ignoring non-hydrogen chemical shift line (" << text_line << ")" << std::endl;
664  continue;
665  }
666 
667  if(is_polar_hydrogen(input_atom_name)){
668  if(false) std::cout << "Ignoring polar hydrogen chemical shift line (" << text_line << ")" << std::endl;
669  continue;
670  }
671 
672  //Assume that input_atom_name is a non_polar hydrogen atom! Other atoms should be filtered before reaching this point!
673  std::string const atom_name=get_rosetta_hatom_name(input_atom_name, text_line, flat_proton_entry_list);
674 
675  Size const realatomdata_index=get_realatomdata_index(atom_name, res_aa);
676 
677  Real const exp_shift=string_to_real(text_line_list[7]);
678 
679  ChemicalShiftData const chem_shift_data( seq_num, res_aa, atom_name, realatomdata_index, exp_shift, text_line);
680 
681  assert_is_calc_chem_shift_atom(chem_shift_data);
682 
683  flat_EXP_chem_shift_data_list.push_back(chem_shift_data);
684 
685  if(max_seq_num<seq_num) max_seq_num=seq_num;
686 
687  }
688 
689  //////////////////////////////////////////////////////////////////////
690  if(include_res_list.size()==0){
691  TR << "User did not pass in score:rna_chemical_shift_include_res, including all residue:";
692  for(Size seq_num=1; seq_num<=max_seq_num; seq_num++){
693  include_res_list.push_back(seq_num);
694  TR << " " << seq_num;
695  }
696  TR << std::endl;
697  }else{
698  TR << "User pass in score:rna_chemical_shift_include_res:";
699  for(Size res_ID=1; res_ID<=include_res_list.size(); res_ID++){
700  TR << " " << include_res_list[res_ID];
701  }
702  TR << std::endl;
703  }
704 
705  //////////////////////////////////////////////////////////////////////
707 
708  for(Size proton_entry_ID=1; proton_entry_ID<=proton_entry_list.size(); proton_entry_ID++){
709 
710  for(Size res_ID=1; res_ID<=include_res_list.size(); res_ID++){
711 
712  Size const seq_num=include_res_list[res_ID];
713  utility::vector1< std::string > const proton_entry= proton_entry_list[proton_entry_ID];
714 
715  utility::vector1 < ChemicalShiftData > const & filterd_CS_data_list=filter_chem_shift_data_list(flat_EXP_chem_shift_data_list, seq_num, proton_entry);
716 
717  if(filterd_CS_data_list.size()!=0){
718  EXP_chem_shift_data_list_.push_back(filterd_CS_data_list);
719  }
720  }
721 
722  }
723 
724  //////////////////////////////////////////////////////////////////////
726 
727  for(Size outer_data_ID=1; outer_data_ID<=EXP_chem_shift_data_list_.size(); outer_data_ID++){
728 
729  utility::vector1 < ChemicalShiftData > const & EXP_chem_shift_data_entry=EXP_chem_shift_data_list_[outer_data_ID];
730 
731  utility::vector1 < Real > mock_calc_chem_shift_entry;
732  for(Size inner_data_ID=1; inner_data_ID<=EXP_chem_shift_data_entry.size(); inner_data_ID++){
733  mock_calc_chem_shift_entry.push_back(0.0);
734  }
735 
736  utility::vector1 < Real > actual_exp_chem_shift_entry;
737  utility::vector1 < bool > do_include_CS_data;
738 
739  get_best_exp_to_calc_chem_shift_mapping(EXP_chem_shift_data_entry, mock_calc_chem_shift_entry, actual_exp_chem_shift_entry, do_include_CS_data);
740 
741 
742  for(Size inner_data_ID=1; inner_data_ID<=EXP_chem_shift_data_entry.size(); inner_data_ID++){
743 
744  if(do_include_CS_data[inner_data_ID]==false) continue;
745 
747 
748  }
749  }
750  std::cout << "total_exp_chemical_shift_data_points_ (possibly ignoring duplicates)= " << total_exp_chemical_shift_data_points_ << std::endl;
751 
752  //////////////////////////////////////////////////////////////////////
753  Size data_count=0;
754 
755  if(verbose_){
756 
757  std::cout << "------------------Imported exp_chem_shift_data_list------------------" << std::endl;
758  for(Size ii=1; ii<=EXP_chem_shift_data_list_.size(); ii++){
759  for(Size jj=1; jj<=EXP_chem_shift_data_list_[ii].size(); jj++){
760  data_count++;
761 
762  std::string const prefix="#" + lead_zero_string_of(ii, 3) + "." + lead_zero_string_of(jj, 1) + " | count= " + lead_zero_string_of(data_count, 3) + " :";
763 
765  }
766  }
767  std::cout << "---------------------------------------------------------------------" << std::endl;
768  }
769  //////////////////////////////////////////////////////////////////////
770 
771  }
772 
773  //////////////////////////////////////////////////////////////////////
774  Real
776 
777  if( (CS_data.seq_num<1) || (CS_data.seq_num>pose.total_residue()) ){
778  std::cout << "ERROR: CS_data.seq_num=" << CS_data.seq_num << std::endl;
779  std::cout << "ERROR: pose.total_residue()=" << pose.total_residue() << std::endl;
780  utility_exit_with_message("(CS_data.seq_num<1) || (CS_data.seq_num>pose.total_residue())");
781  }
782 
783  if(CS_data.res_aa!=pose.residue(CS_data.seq_num).aa()){
784  std::cout << "ERROR: CS_data.res_aa=" << CS_data.res_aa << std::endl;
785  std::cout << "ERROR: CS_data.seq_num=" << CS_data.seq_num << std::endl;
786  std::cout << "ERROR: pose.residue(CS_data.seq_num).aa()=" << pose.residue(CS_data.seq_num).aa() << std::endl;
787  utility_exit_with_message("chem_shift_data.res_aa!=pose1.residue(CS_data.seq_num).aa()");
788  }
789 
790  Real calc_chem_shift=0.0;
791 
792  core::conformation::Residue const & curr_rsd = pose.residue(CS_data.seq_num);
793 
794  RNA_CS_residue_parameters const & rna_cs_curr_rsd_params=rna_cs_params_.get_RNA_CS_residue_parameters(curr_rsd.aa());
795 
796  Size const curr_atom_index=curr_rsd.atom_index( CS_data.atom_name );
797 
798  numeric::xyzVector<core::Real> const & curr_atom_xyz = curr_rsd.xyz(curr_atom_index);
799 
800  bool curr_atom_is_sugar=( dround( rna_cs_curr_rsd_params.atom_data(CS_data.realatomdata_index, suga) ) == 1 ); //NUCHEMIC defines phosphate as part of sugar!
801 
802  bool curr_atom_is_base=(curr_atom_is_sugar==false);
803 
804  calc_chem_shift+=rna_cs_curr_rsd_params.atom_data(CS_data.realatomdata_index, oshi); //reference offset
805 
806  for(Size seq_num=1; seq_num<=pose.total_residue(); seq_num++){
807 
808  core::conformation::Residue const & source_rsd = pose.residue(seq_num);
809 
810  RNA_CS_residue_parameters const & source_rsd_CS_params=rna_cs_params_.get_RNA_CS_residue_parameters(source_rsd.aa());
811 
812  if( (CS_data.seq_num == seq_num) && (curr_atom_is_base) ) continue;
813 
814  if(include_ring_current_effect_) calc_chem_shift += ring_current_effect( curr_atom_xyz, source_rsd, source_rsd_CS_params);
815  if(include_magnetic_anisotropy_effect_) calc_chem_shift += magnetic_anisotropy_effect(curr_atom_xyz, source_rsd, source_rsd_CS_params);
816 
817  }
818 
819 
820  if(false){ /*verbose_*/
821 
822  std::cout << rna_cs_curr_rsd_params.base_name() << " " << CS_data.seq_num << " " << CS_data.atom_name << "\n";
823 
824  std::cout << "duetores : rc ma\n";
825  for(Size seq_num=1; seq_num<=pose.total_residue(); seq_num++){
826 
827  core::conformation::Residue const & source_rsd = pose.residue(seq_num);
828 
829  RNA_CS_residue_parameters const & source_rsd_CS_params=rna_cs_params_.get_RNA_CS_residue_parameters(source_rsd.aa());
830 
831  std::cout << " " << source_rsd_CS_params.base_name() << " " << seq_num << " : ";
832 
833  if( (CS_data.seq_num == seq_num) && (curr_atom_is_base) ){
834  std::cout << "0 0\n";
835  }else{
836  std::cout << ring_current_effect( curr_atom_xyz, source_rsd, source_rsd_CS_params) << " ";
837  std::cout << magnetic_anisotropy_effect(curr_atom_xyz, source_rsd, source_rsd_CS_params) << "\n";
838  }
839 
840  }
841  std::cout << "offset : " << rna_cs_curr_rsd_params.atom_data(CS_data.realatomdata_index, oshi) << "\n";
842  std::cout << "charge effect : " << 0.0 << "\n\n\n"; //Currently electric field effect is not yet implemented.
843  }
844 
845  return calc_chem_shift;
846 
847  }
848 
849  //////////////////////////////////////////////////////////////////////
850  void
852 
853  calc_chem_shift_list.clear();
854 
855  for(Size outer_data_ID=1; outer_data_ID<=EXP_chem_shift_data_list_.size(); outer_data_ID++){
856  utility::vector1 < Real > calc_chem_shift_entry;
857  calc_chem_shift_entry.clear();
858 
859  for(Size inner_data_ID=1; inner_data_ID<=EXP_chem_shift_data_list_[outer_data_ID].size(); inner_data_ID++){
860 
861  ChemicalShiftData const & CS_data=EXP_chem_shift_data_list_[outer_data_ID][inner_data_ID];
862 
863  Real const calc_chem_shift = get_calc_chem_shift_value( CS_data, pose);
864 
865  calc_chem_shift_entry.push_back(calc_chem_shift);
866 
867  }
868 
869  calc_chem_shift_list.push_back(calc_chem_shift_entry);
870  }
871 
872  //Consistency_check:
873  if(calc_chem_shift_list.size()!=EXP_chem_shift_data_list_.size()){
874  utility_exit_with_message("calc_chem_shift_list.size()!=EXP_chem_shift_data_list_.size()");
875  }
876 
877  for(Size ii=1; ii<=EXP_chem_shift_data_list_.size(); ii++){
878  if(EXP_chem_shift_data_list_[ii].size()!=calc_chem_shift_list[ii].size()){
879  utility_exit_with_message("EXP_chem_shift_data_list_[ii].size()!=calc_chem_shift_list[ii].size()");
880  }
881  }
882 
883  }
884 
885  /////////////////////////////////////////////////////////////////////////////
886  void
888  utility::vector1 < Real > const & calc_chem_shift_entry,
889  utility::vector1 < Real > & actual_exp_chem_shift_entry,
890  utility::vector1 < bool > & do_include_CS_data) const {
891 
892  using namespace ObjexxFCL;
893 
894  actual_exp_chem_shift_entry.clear();
895  do_include_CS_data.clear();
896 
897  if(EXP_chem_shift_data_entry.size()!=calc_chem_shift_entry.size()){
898  utility_exit_with_message("EXP_chem_shift_data_entry.size()!=calc_chem_shift_entry.size()");
899  }
900 
901 
902  if(EXP_chem_shift_data_entry.size()==2){ // Two choice either direct or flipped match.
903 
904  //Choose the one that minimize the error (best fit "least-square regression")!
905  //"Least squares" means that the overall solution minimizes the sum of the squares of the errors made in solving every single equation
906  //Least squares corresponds to the maximum likelihood criterion if the experimental errors have a normal distribution and can also be derived as a method of moments estimator.
907 
908  ChemicalShiftData const & CS_data_one=EXP_chem_shift_data_entry[1];
909  ChemicalShiftData const & CS_data_two=EXP_chem_shift_data_entry[2];
910 
911  Real const calc_shift_one=calc_chem_shift_entry[1];
912  Real const calc_shift_two=calc_chem_shift_entry[2];
913 
914  /////Consistency checks..comment out if this slows down code!/////////
915  if(CS_data_one.seq_num!=CS_data_two.seq_num) utility_exit_with_message("CS_data_one.seq_num!=CS_data_two.seq_num");
916 
917  Size num_matching_atom_pairs_found=0;
918 
919  if(CS_data_one.atom_name=="1H5*" && CS_data_two.atom_name=="2H5*") num_matching_atom_pairs_found++;
920 
921  if(CS_data_one.atom_name=="2H5*" && CS_data_two.atom_name=="1H5*") num_matching_atom_pairs_found++;
922 
923  if(num_matching_atom_pairs_found!=1) utility_exit_with_message("num_matching_atom_pairs_found=(" +string_of(num_matching_atom_pairs_found)+")!=1");
924  ///////////////////////////////////////////////////////////////////////
925 
926 
927  if( (H5_prime_mode_=="LEAST_SQUARE_IGNORE_DUPLICATE") && (std::fabs(CS_data_one.exp_shift-CS_data_two.exp_shift)<0.00001) ){ //A duplicated entry!
928 
929  if( std::pow(calc_shift_one-CS_data_one.exp_shift, 2) < std::pow(calc_shift_two-CS_data_two.exp_shift, 2) ){ //Choose the one that minimize the difference!
930 
931  if( false ){/*verbose_*/
932  std::cout << "---------------------------------------------------" << std::endl;
933  std::cout << "Keeping the better_fit of the duplicated H5_prime data | calc_shift_one=" << calc_shift_one; print_chemical_shift_data("CS_data_one:", CS_data_one, true);
934  std::cout << "Ignoring the worst_fit of the duplicated H5_prime data | calc_shift_two=" << calc_shift_two; print_chemical_shift_data("CS_data_two:", CS_data_two, true);
935  std::cout << "---------------------------------------------------" << std::endl;
936  }
937 
938  do_include_CS_data.push_back(true);
939  do_include_CS_data.push_back(false);
940  actual_exp_chem_shift_entry.push_back(CS_data_one.exp_shift);
941  actual_exp_chem_shift_entry.push_back(0.0);
942 
943 
944  }else{
945 
946  if( false ){/*verbose_*/
947  std::cout << "---------------------------------------------------" << std::endl;
948  std::cout << "Keeping the better_fit of the duplicated H5_prime data | calc_shift_two=" << calc_shift_two; print_chemical_shift_data("CS_data_two:", CS_data_two, true);
949  std::cout << "Ignoring the worst_fit of the duplicated H5_prime data | calc_shift_one=" << calc_shift_one; print_chemical_shift_data("CS_data_one:", CS_data_one, true);
950  std::cout << "---------------------------------------------------" << std::endl;
951  }
952 
953  //Include the first exp_CS_data in the entry but not the second.
954  do_include_CS_data.push_back(false);
955  do_include_CS_data.push_back(true);
956  actual_exp_chem_shift_entry.push_back(0.0);
957  actual_exp_chem_shift_entry.push_back(CS_data_one.exp_shift);
958 
959  }
960 
961  }else{
962 
963  do_include_CS_data.push_back(true);
964  do_include_CS_data.push_back(true);
965 
966  Real const sum_error_square_choice_one= std::pow(calc_shift_one-CS_data_one.exp_shift, 2) + std::pow(calc_shift_two-CS_data_two.exp_shift, 2);
967  Real const sum_error_square_choice_two= std::pow(calc_shift_one-CS_data_two.exp_shift, 2) + std::pow(calc_shift_two-CS_data_one.exp_shift, 2);
968 
969  if(sum_error_square_choice_one<sum_error_square_choice_two){
970  actual_exp_chem_shift_entry.push_back(CS_data_one.exp_shift);
971  actual_exp_chem_shift_entry.push_back(CS_data_two.exp_shift);
972  }else{
973  actual_exp_chem_shift_entry.push_back(CS_data_two.exp_shift);
974  actual_exp_chem_shift_entry.push_back(CS_data_one.exp_shift);
975  }
976  }
977 
978  }else if(EXP_chem_shift_data_entry.size()==1){
979 
980  do_include_CS_data.push_back(true);
981  actual_exp_chem_shift_entry.push_back(EXP_chem_shift_data_entry[1].exp_shift);
982 
983  }else{
984  std::cout << "ERROR: EXP_chem_shift_data_entry.size()= " << EXP_chem_shift_data_entry.size() << std::endl;
985  utility_exit_with_message("EXP_chem_shift_data_entry.size()!=1 and EXP_chem_shift_data_entry.size()!=2");
986  }
987 
988 
989  }
990 
991  /////////////////////////////////////////////////////////////////////////////
992  core::Real
994 
995  using namespace ObjexxFCL;
996 
997  //Consistency_check:
998  if(calc_chem_shift_list.size()!=EXP_chem_shift_data_list_.size()){
999  utility_exit_with_message("cal_chem_shift_list.size()!=EXP_chem_shift_data_list_.size()");
1000  }
1001 
1002  Real chem_shift_energy=0.0;
1003 
1004  for(Size outer_data_ID=1; outer_data_ID<=EXP_chem_shift_data_list_.size(); outer_data_ID++){
1005 
1006  utility::vector1 < ChemicalShiftData > const & EXP_chem_shift_data_entry=EXP_chem_shift_data_list_[outer_data_ID];
1007  utility::vector1 < Real > const & calc_chem_shift_entry=calc_chem_shift_list[outer_data_ID];
1008 
1009  utility::vector1 < Real > actual_exp_chem_shift_entry;
1010  utility::vector1 < bool > do_include_CS_data;
1011 
1012  get_best_exp_to_calc_chem_shift_mapping(EXP_chem_shift_data_entry, calc_chem_shift_entry, actual_exp_chem_shift_entry, do_include_CS_data);
1013 
1014  for(Size inner_data_ID=1; inner_data_ID<=EXP_chem_shift_data_entry.size(); inner_data_ID++){
1015 
1016  if(do_include_CS_data[inner_data_ID]==false) continue;
1017 
1018  Real const exp_chem_shift=actual_exp_chem_shift_entry[inner_data_ID];
1019 
1020  Real const calc_chem_shift=calc_chem_shift_entry[inner_data_ID];
1021 
1022  chem_shift_energy+=std::pow(calc_chem_shift-exp_chem_shift, 2);
1023 
1024  }
1025 
1026  }
1027 
1028  return chem_shift_energy;
1029  }
1030 
1031  ///////////////////////////////////////////////////////////////////////////////
1032  void
1034  using namespace conformation;
1035 
1036  for(Size seq_num=1; seq_num<=pose.total_residue(); seq_num++){ //Right now assume pure RNA molecule.
1037  if(pose.residue( seq_num ).is_RNA()==false) return;
1038  }
1039 
1040  utility::vector1 < utility::vector1 < Real > > cal_chem_shift_list;
1041  cal_chem_shift_list.clear();
1042 
1043  update_calc_chem_shift_list(pose, cal_chem_shift_list);
1044 
1045  Real const chem_shift_score=get_chemical_shift_energy(cal_chem_shift_list);
1046 
1047  totals[ rna_chem_shift ] = chem_shift_score;
1048 
1049 
1050  } // finalize_total_energy
1051 
1052  ///////////////////////////////////////////////////////////////////////////////
1053  ///Derivative of the specified CS_data atom (non-polar proton). Both ring current and magnetic_anisotropy effects
1054  ///This function should be called once for each CS_data atom!
1055 
1056  void
1058  pose::Pose const & pose,
1059  conformation::Residue const & CS_data_rsd,
1060  Size const CS_data_atomno,
1061  Vector & f1,
1062  Vector & f2
1063  ) const {
1064 
1065  using namespace ObjexxFCL;
1066 
1067  std::string const CS_data_atom_name=remove_whitespaces(CS_data_rsd.atom_name(CS_data_atomno));
1068 
1069  utility::vector1 < ChemicalShiftData > const & EXP_chem_shift_data_entry=get_matching_CS_data_entry( CS_data_rsd.seqpos(), CS_data_atom_name );
1070 
1071  utility::vector1 < Real > calc_chem_shift_entry;
1072  for(Size inner_data_ID=1; inner_data_ID<=EXP_chem_shift_data_entry.size(); inner_data_ID++){
1073  ChemicalShiftData const & CS_data=EXP_chem_shift_data_entry[inner_data_ID];
1074  Real const calc_chem_shift= get_calc_chem_shift_value(CS_data, pose);
1075  calc_chem_shift_entry.push_back(calc_chem_shift);
1076  }
1077 
1078  utility::vector1 < Real > actual_exp_chem_shift_entry;
1079  utility::vector1 < bool > do_include_CS_data;
1080 
1081  //RIGHT NOW ANALYTICAL DERIV OVER PREDICTS NUMERICAL DERIV AT places where chem shift of H5' ~ chem_shift of H5''.
1082  //FIX THIS by using a fade function?
1083  get_best_exp_to_calc_chem_shift_mapping(EXP_chem_shift_data_entry, calc_chem_shift_entry, actual_exp_chem_shift_entry, do_include_CS_data);
1084 
1085  for(Size inner_data_ID=1; inner_data_ID<=EXP_chem_shift_data_entry.size(); inner_data_ID++){
1086 
1087  ChemicalShiftData const & possible_CS_data=EXP_chem_shift_data_entry[inner_data_ID];
1088 
1089  if(EXP_chem_shift_data_entry.size()!=1){//DEAL WITH SPECIAL CASE (H5'/H5'' and etcs).
1090  if(CS_data_atom_name!=possible_CS_data.atom_name) continue;
1091  //if(CS_data_atomno!=CS_data_rsd.atom_index(CS_data.atom_name)) continue;
1092  }
1093 
1094  ChemicalShiftData const & CS_data= possible_CS_data;
1095 
1096  if(do_include_CS_data[inner_data_ID]==false) continue;
1097 
1098  Real const calc_chem_shift= calc_chem_shift_entry[inner_data_ID];
1099 
1100  Real const act_exp_chem_shift= actual_exp_chem_shift_entry[inner_data_ID];
1101 
1102  if( false ){ /*verbose_*/
1103  std::string const pre_string = "get_deriv_for_chemical_shift_data_atom | jj= " + string_of(inner_data_ID) + " | EXP_CS_data_entry.size()= " + string_of(EXP_chem_shift_data_entry.size()) +": ";
1104  print_chemical_shift_data(pre_string, CS_data, false /*print_data_line*/);
1105  }
1106 
1107  if(CS_data.res_aa!=pose.residue(CS_data.seq_num).aa()){
1108  print_chemical_shift_data("ERROR CS_data:", CS_data, true);
1109  std::cout << "ERROR: pose.residue(CS_data.seq_num).aa()=" << pose.residue(CS_data.seq_num).aa() << std::endl;
1110  utility_exit_with_message("CS_data.res_aa!=pose1.residue(CS_data.seq_num).aa()");
1111  }
1112 
1113 
1114  RNA_CS_residue_parameters const & CS_data_rsd_CS_params=rna_cs_params_.get_RNA_CS_residue_parameters(CS_data.res_aa);
1115 
1116  bool const CS_data_atom_is_sugar=( dround(CS_data_rsd_CS_params.atom_data(CS_data.realatomdata_index, suga) ) == 1 ); //NUCHEMIC defines phosphate as part of sugar!
1117 
1118  bool const CS_data_atom_is_base=(CS_data_atom_is_sugar==false);
1119 
1120  Size const CS_data_atom_index=CS_data_rsd.atom_index( CS_data.atom_name );
1121 
1122  numeric::xyzVector<core::Real> const & CS_data_atom_xyz = CS_data_rsd.xyz(CS_data_atom_index);
1123 
1124  for(Size source_seq_num=1; source_seq_num<=pose.total_residue(); source_seq_num++){
1125 
1126  core::conformation::Residue const & source_rsd = pose.residue(source_seq_num);
1127 
1128  RNA_CS_residue_parameters const & source_rsd_CS_params=rna_cs_params_.get_RNA_CS_residue_parameters(source_rsd.aa());
1129 
1130  if( (CS_data.seq_num == source_seq_num) && (CS_data_atom_is_base) ) continue;
1131 
1133  ///Ring current effects
1134  for(Size ring_ID=1; ring_ID<=source_rsd_CS_params.num_rings(); ring_ID++){
1135 
1136  //get_ring_current_deriv() gives gradient of ring_current_effect() wrt to r_vector
1137  // +1.0 since r_vector = CS_data_atom_xyz - molecular_ring_center.
1138  numeric::xyzVector<core::Real> const f2_calc_chem_shift = +1.0 * get_ring_current_deriv(CS_data_atom_xyz, source_rsd, ring_ID, source_rsd_CS_params);
1139  numeric::xyzVector<core::Real> const f1_calc_chem_shift = cross( f2_calc_chem_shift, CS_data_atom_xyz);
1140 
1141  f1+= 2.0*(calc_chem_shift-act_exp_chem_shift)*(f1_calc_chem_shift); //Convert deriv_vector of calc_chem_shift to deriv_vector of chemical_shift_energy
1142  f2+= 2.0*(calc_chem_shift-act_exp_chem_shift)*(f2_calc_chem_shift); //Convert deriv_vector of calc_chem_shift to deriv_vector of chemical_shift_energy
1143 
1144  }
1145  }
1146 
1148  //Magnetic_anisotropy effects
1149  Size const source_rsd_maxatoms=source_rsd_CS_params.get_atomnames_size();
1150 
1151  numeric::xyzMatrix< core::Real > const source_base_coordinate_matrix = get_rna_base_coordinate_system_from_CS_params(source_rsd, source_rsd_CS_params);
1152 
1153  for(Size source_realatomdata_index=1; source_realatomdata_index<=source_rsd_maxatoms; source_realatomdata_index++){
1154 
1155  if( dround(source_rsd_CS_params.atom_data(source_realatomdata_index, maca)) != 1 ) continue;
1156 
1157  Size const source_atom_index=source_rsd.atom_index( source_rsd_CS_params.get_atomname(source_realatomdata_index) );
1158 
1159  numeric::xyzVector<core::Real> const & source_atom_xyz = source_rsd.xyz(source_atom_index);
1160 
1161  //get_delta_magnetic_anisotropy_deriv() gives gradient of delta_magnetic_anisotropy() with respect to r_vector.
1162  // +1.0 since r_vector = CS_data_atom_xyz - source_atom_xyz.
1163  numeric::xyzVector<core::Real> const f2_calc_chem_shift = +1.0 * get_delta_magnetic_anisotropy_deriv(CS_data_atom_xyz, source_atom_xyz, source_base_coordinate_matrix, source_rsd_CS_params, source_realatomdata_index);
1164 
1165  numeric::xyzVector<core::Real> const f1_calc_chem_shift = cross( f2_calc_chem_shift, CS_data_atom_xyz);
1166 
1167  f1+= 2.0*(calc_chem_shift-act_exp_chem_shift)*(f1_calc_chem_shift); //Convert deriv_vector of calc_chem_shift to deriv_vector of chemical_shift_energy
1168  f2+= 2.0*(calc_chem_shift-act_exp_chem_shift)*(f2_calc_chem_shift); //Convert deriv_vector of calc_chem_shift to deriv_vector of chemical_shift_energy
1169 
1170 
1171  }
1172  }
1173 
1174 
1175  }
1176 
1177  }
1178 
1179  }
1180 
1181 
1182  ///////////////////////////////////////////////////////////////////////////////
1183  ///Derivative due to the ring_current effect of the source base. Include contribution from all CS_data atoms (non-polar protons).
1184  ///Note, there are 1 or 2 ring centers per base.
1185  ///This function should be called once for each residue only at the first_base_atomno.
1186 
1187  void
1189  pose::Pose const & pose,
1190  conformation::Residue const & rc_source_rsd,
1191  Size const chi1_torsion_atomnno,
1192  Vector & f1,
1193  Vector & f2
1194  ) const {
1195 
1196  if(include_ring_current_effect_==false) return;
1197 
1198  Size const rc_source_seq_num=rc_source_rsd.seqpos();
1199 
1200  RNA_CS_residue_parameters const & rc_source_rsd_CS_params=rna_cs_params_.get_RNA_CS_residue_parameters(rc_source_rsd.aa());
1201 
1202  std::string const chi1_torsion_atomn_name=rc_source_rsd.atom_name(chi1_torsion_atomnno);
1203 
1204  if( false ){ /*verbose_*/
1205  std::cout << "get_deriv_for_ring_current_center for chi1_torsion_atomn_name=" << chi1_torsion_atomn_name;
1206  std::cout << " | name_from_aa(rc_source_rsd.aa())= " << name_from_aa(rc_source_rsd.aa());
1207  std::cout << " | rc_source_seq_num= " << rc_source_seq_num;
1208  }
1209 
1210  //Enumerate through all the chemical_shift data points (right now only non_polar protons).
1211  for(Size outer_data_ID=1; outer_data_ID<=EXP_chem_shift_data_list_.size(); outer_data_ID++){
1212 
1213  utility::vector1 < ChemicalShiftData > const & EXP_chem_shift_data_entry=EXP_chem_shift_data_list_[outer_data_ID];
1214 
1215  utility::vector1 < Real > calc_chem_shift_entry;
1216  for(Size inner_data_ID=1; inner_data_ID<=EXP_chem_shift_data_entry.size(); inner_data_ID++){
1217 
1218  ChemicalShiftData const & CS_data=EXP_chem_shift_data_entry[inner_data_ID];
1219  Real const calc_chem_shift= get_calc_chem_shift_value(CS_data, pose);
1220  calc_chem_shift_entry.push_back(calc_chem_shift);
1221  }
1222 
1223  utility::vector1 < Real > actual_exp_chem_shift_entry;
1224  utility::vector1 < bool > do_include_CS_data;
1225 
1226  get_best_exp_to_calc_chem_shift_mapping(EXP_chem_shift_data_entry, calc_chem_shift_entry, actual_exp_chem_shift_entry, do_include_CS_data);
1227 
1228  for(Size inner_data_ID=1; inner_data_ID<=EXP_chem_shift_data_entry.size(); inner_data_ID++){
1229 
1230  if(do_include_CS_data[inner_data_ID]==false) continue;
1231 
1232  ChemicalShiftData const & CS_data=EXP_chem_shift_data_entry[inner_data_ID];
1233 
1234  Real const calc_chem_shift= calc_chem_shift_entry[inner_data_ID];
1235 
1236  Real const act_exp_chem_shift= actual_exp_chem_shift_entry[inner_data_ID];
1237 
1238  core::conformation::Residue const & CS_data_rsd = pose.residue(CS_data.seq_num);
1239 
1240  Size const CS_data_atom_index=CS_data_rsd.atom_index( CS_data.atom_name );
1241 
1242  numeric::xyzVector<core::Real> const & CS_data_atom_xyz = CS_data_rsd.xyz(CS_data_atom_index);
1243 
1244  RNA_CS_residue_parameters const & CS_data_rsd_CS_params=rna_cs_params_.get_RNA_CS_residue_parameters(CS_data.res_aa);
1245 
1246  bool const CS_data_atom_is_sugar=( dround( CS_data_rsd_CS_params.atom_data(CS_data.realatomdata_index, suga) ) == 1 ); //NUCHEMIC defines phosphate as part of sugar!
1247 
1248  bool const CS_data_atom_is_base=(CS_data_atom_is_sugar==false);
1249 
1250  if( (CS_data.seq_num == rc_source_seq_num) && (CS_data_atom_is_base) ) continue;
1251 
1252  for(Size rc_source_ring_ID=1; rc_source_ring_ID<=rc_source_rsd_CS_params.num_rings(); rc_source_ring_ID++){
1253 
1254  //get_ring_current_deriv() gives gradient of ring_current_effect() wrt to r_vector
1255  // -1.0 since r_vector = CS_data_atom_xyz - molecular_ring_center.
1256  numeric::xyzVector<core::Real> const f2_calc_chem_shift = -1.0 * get_ring_current_deriv(CS_data_atom_xyz, rc_source_rsd, rc_source_ring_ID, rc_source_rsd_CS_params);
1257  numeric::xyzVector<core::Real> const f1_calc_chem_shift = cross( f2_calc_chem_shift, CS_data_atom_xyz); //cross( f2_calc_chem_shift, ring_center_xyz);
1258 
1259  f1+= 2.0*(calc_chem_shift-act_exp_chem_shift)*(f1_calc_chem_shift); //Convert deriv_vector of calc_chem_shift to deriv_vector of chemical_shift_energy
1260  f2+= 2.0*(calc_chem_shift-act_exp_chem_shift)*(f2_calc_chem_shift); //Convert deriv_vector of calc_chem_shift to deriv_vector of chemical_shift_energy
1261 
1262  }
1263  }
1264  }
1265  }
1266 
1267  ///////////////////////////////////////////////////////////////////////////////
1268  ///Derivative due to the manisotropy effect of the source base. Include contribution from all CS_data atoms (non-polar protons).
1269  ///This function should be called once for each residue only at the chi1_torsion_atomno.
1270  void
1272  pose::Pose const & pose,
1273  conformation::Residue const & ma_source_rsd,
1274  Size const chi1_torsion_atomno,
1275  Vector & f1,
1276  Vector & f2
1277  ) const {
1278 
1279  if(include_magnetic_anisotropy_effect_==false) return;
1280 
1281  Size const ma_source_seq_num=ma_source_rsd.seqpos();
1282 
1283  RNA_CS_residue_parameters const & ma_source_rsd_CS_params=rna_cs_params_.get_RNA_CS_residue_parameters(ma_source_rsd.aa());
1284 
1285  std::string const chi1_torsion_atom_name=ma_source_rsd.atom_name(chi1_torsion_atomno);
1286 
1287  Size const ma_source_rsd_maxatoms=ma_source_rsd_CS_params.get_atomnames_size();
1288 
1289  numeric::xyzMatrix< core::Real > const ma_source_base_coordinate_matrix = get_rna_base_coordinate_system_from_CS_params(ma_source_rsd, ma_source_rsd_CS_params);
1290 
1291  if( false ){ /*verbose_*/
1292  std::cout << "get_deriv_for_magnetic_anisotropy_src_atom for chi1_torsion_atom_name=" << chi1_torsion_atom_name;
1293  std::cout << " | name_from_aa(ma_source_rsd.aa())= " << name_from_aa(ma_source_rsd.aa());
1294  std::cout << " | ma_source_seq_num= " << ma_source_seq_num << std::endl;
1295  }
1296 
1297  //Enumerate through all the chemical_shift data points (right now only non_polar protons).
1298  for(Size outer_data_ID=1; outer_data_ID<=EXP_chem_shift_data_list_.size(); outer_data_ID++){
1299 
1300  utility::vector1 < ChemicalShiftData > const & EXP_chem_shift_data_entry=EXP_chem_shift_data_list_[outer_data_ID];
1301 
1302  utility::vector1 < Real > calc_chem_shift_entry;
1303  for(Size inner_data_ID=1; inner_data_ID<=EXP_chem_shift_data_entry.size(); inner_data_ID++){
1304 
1305  ChemicalShiftData const & CS_data=EXP_chem_shift_data_entry[inner_data_ID];
1306  Real const calc_chem_shift= get_calc_chem_shift_value(CS_data, pose);
1307  calc_chem_shift_entry.push_back(calc_chem_shift);
1308  }
1309 
1310  utility::vector1 < Real > actual_exp_chem_shift_entry;
1311  utility::vector1 < bool > do_include_CS_data;
1312 
1313  //RIGHT NOW ANALYTICAL DERIV OVER PREDICTS NUMERICAL DERIV AT places where chem shift of H5' ~ chem_shift of H5''.
1314  //FIX THIS by using a fade function?
1315  get_best_exp_to_calc_chem_shift_mapping(EXP_chem_shift_data_entry, calc_chem_shift_entry, actual_exp_chem_shift_entry, do_include_CS_data);
1316 
1317  for(Size inner_data_ID=1; inner_data_ID<=EXP_chem_shift_data_entry.size(); inner_data_ID++){
1318 
1319  if(do_include_CS_data[inner_data_ID]==false) continue;
1320 
1321  ChemicalShiftData const & CS_data=EXP_chem_shift_data_entry[inner_data_ID];
1322 
1323  Real const calc_chem_shift= calc_chem_shift_entry[inner_data_ID];
1324 
1325  Real const act_exp_chem_shift= actual_exp_chem_shift_entry[inner_data_ID];
1326 
1327  core::conformation::Residue const & CS_data_rsd = pose.residue(CS_data.seq_num);
1328 
1329  Size const CS_data_atom_index=CS_data_rsd.atom_index( CS_data.atom_name );
1330 
1331  numeric::xyzVector<core::Real> const & CS_data_atom_xyz = CS_data_rsd.xyz(CS_data_atom_index);
1332 
1333  RNA_CS_residue_parameters const & CS_data_rsd_CS_params=rna_cs_params_.get_RNA_CS_residue_parameters(CS_data.res_aa);
1334 
1335  bool const CS_data_atom_is_sugar=( dround( CS_data_rsd_CS_params.atom_data(CS_data.realatomdata_index, suga) ) == 1 ); //NUCHEMIC defines phosphate as part of sugar!
1336 
1337  bool const CS_data_atom_is_base=(CS_data_atom_is_sugar==false);
1338 
1339  if( (CS_data.seq_num == ma_source_seq_num) && (CS_data_atom_is_base) ) continue;
1340 
1341  for(Size source_realatomdata_index=1; source_realatomdata_index<=ma_source_rsd_maxatoms; source_realatomdata_index++){
1342 
1343  if( dround(ma_source_rsd_CS_params.atom_data(source_realatomdata_index, maca)) != 1 ) continue;
1344 
1345  Size const ma_source_atom_index=ma_source_rsd.atom_index( ma_source_rsd_CS_params.get_atomname(source_realatomdata_index) );
1346 
1347  numeric::xyzVector<core::Real> const & ma_source_atom_xyz = ma_source_rsd.xyz(ma_source_atom_index);
1348 
1349  //get_delta_magnetic_anisotropy_deriv() gives gradient of delta_magnetic_anisotropy() with respect to r_vector.
1350  // -1.0 since r_vector = CS_data_atom_xyz - source_atom_xyz.
1351  numeric::xyzVector<core::Real> const f2_calc_chem_shift = -1.0 * get_delta_magnetic_anisotropy_deriv(CS_data_atom_xyz, ma_source_atom_xyz, ma_source_base_coordinate_matrix, ma_source_rsd_CS_params, source_realatomdata_index);
1352 
1353  numeric::xyzVector<core::Real> const f1_calc_chem_shift = cross( f2_calc_chem_shift, CS_data_atom_xyz);
1354 
1355  f1+= 2.0*(calc_chem_shift-act_exp_chem_shift)*(f1_calc_chem_shift); //Convert deriv_vector of calc_chem_shift to deriv_vector of chemical_shift_energy
1356  f2+= 2.0*(calc_chem_shift-act_exp_chem_shift)*(f2_calc_chem_shift); //Convert deriv_vector of calc_chem_shift to deriv_vector of chemical_shift_energy
1357 
1358 
1359  }
1360  }
1361  }
1362 
1363  }
1364 
1365  ///////////////////////////////////////////////////////////////////////////////
1366  ///Derivative at the magnetic_anisotropy_src_atom (right how only base heavy-atoms) due to the magnetic_anistropy_effect.
1367  ///Include contribution from all CS_data atoms (non-polar protons).
1368  void
1370  pose::Pose const & pose,
1371  conformation::Residue const & ma_source_rsd,
1372  Size const ma_source_atomno,
1373  Vector & f1,
1374  Vector & f2
1375  ) const {
1376 
1377  if(include_magnetic_anisotropy_effect_==false) return;
1378 
1379  Size const ma_source_seq_num=ma_source_rsd.seqpos();
1380 
1381  RNA_CS_residue_parameters const & ma_source_rsd_CS_params=rna_cs_params_.get_RNA_CS_residue_parameters(ma_source_rsd.aa());
1382 
1383  std::string const ma_source_atom_name=ma_source_rsd.atom_name(ma_source_atomno);
1384 
1385  numeric::xyzMatrix< core::Real > const ma_source_base_coordinate_matrix = get_rna_base_coordinate_system_from_CS_params(ma_source_rsd, ma_source_rsd_CS_params);
1386 
1387  numeric::xyzVector<core::Real> const & ma_source_atom_xyz = ma_source_rsd.xyz(ma_source_atomno);
1388 
1389  Size const ma_source_realatomdata_index=get_realatomdata_index(ma_source_atom_name, ma_source_rsd.aa());
1390 
1391  if( dround(ma_source_rsd_CS_params.atom_data(ma_source_realatomdata_index, maca)) != 1 ){
1392  utility_exit_with_message("dround(ma_source_rsd_CS_params.atom_data(ma_source_realatomdata_index, maca)) != 1");
1393  }
1394 
1395  if( false ){ /*verbose_*/
1396  std::cout << "get_deriv_for_magnetic_anisotropy_src_atom for ma_source_atom_name=" << ma_source_atom_name;
1397  std::cout << " | name_from_aa(ma_source_rsd.aa())= " << name_from_aa(ma_source_rsd.aa());
1398  std::cout << " | ma_source_seq_num= " << ma_source_seq_num << std::endl;
1399  }
1400 
1401  //Enumerate through all the chemical_shift data points (right now only non_polar protons).
1402  for(Size outer_data_ID=1; outer_data_ID<=EXP_chem_shift_data_list_.size(); outer_data_ID++){
1403 
1404  utility::vector1 < ChemicalShiftData > const & EXP_chem_shift_data_entry=EXP_chem_shift_data_list_[outer_data_ID];
1405 
1406  utility::vector1 < Real > calc_chem_shift_entry;
1407  for(Size inner_data_ID=1; inner_data_ID<=EXP_chem_shift_data_entry.size(); inner_data_ID++){
1408 
1409  ChemicalShiftData const & CS_data=EXP_chem_shift_data_entry[inner_data_ID];
1410  Real const calc_chem_shift= get_calc_chem_shift_value(CS_data, pose);
1411  calc_chem_shift_entry.push_back(calc_chem_shift);
1412  }
1413 
1414  utility::vector1 < Real > actual_exp_chem_shift_entry;
1415  utility::vector1 < bool > do_include_CS_data;
1416 
1417  //RIGHT NOW ANALYTICAL DERIV OVER PREDICTS NUMERICAL DERIV AT places where chem shift of H5' ~ chem_shift of H5''.
1418  //FIX THIS by using a fade function?
1419  get_best_exp_to_calc_chem_shift_mapping(EXP_chem_shift_data_entry, calc_chem_shift_entry, actual_exp_chem_shift_entry, do_include_CS_data);
1420 
1421  for(Size inner_data_ID=1; inner_data_ID<=EXP_chem_shift_data_entry.size(); inner_data_ID++){
1422 
1423  if(do_include_CS_data[inner_data_ID]==false) continue;
1424 
1425  ChemicalShiftData const & CS_data=EXP_chem_shift_data_entry[inner_data_ID];
1426 
1427  Real const calc_chem_shift= calc_chem_shift_entry[inner_data_ID];
1428 
1429  Real const act_exp_chem_shift= actual_exp_chem_shift_entry[inner_data_ID];
1430 
1431  core::conformation::Residue const & CS_data_rsd = pose.residue(CS_data.seq_num);
1432 
1433  Size const CS_data_atom_index=CS_data_rsd.atom_index( CS_data.atom_name );
1434 
1435  numeric::xyzVector<core::Real> const & CS_data_atom_xyz = CS_data_rsd.xyz(CS_data_atom_index);
1436 
1437  RNA_CS_residue_parameters const & CS_data_rsd_CS_params=rna_cs_params_.get_RNA_CS_residue_parameters(CS_data.res_aa);
1438 
1439  bool const CS_data_atom_is_sugar=( dround( CS_data_rsd_CS_params.atom_data(CS_data.realatomdata_index, suga) ) == 1 ); //NUCHEMIC defines phosphate as part of sugar!
1440 
1441  bool const CS_data_atom_is_base=(CS_data_atom_is_sugar==false);
1442 
1443  if( (CS_data.seq_num == ma_source_seq_num) && (CS_data_atom_is_base) ) continue;
1444 
1445  //get_delta_magnetic_anisotropy_deriv() gives gradient of delta_magnetic_anisotropy() with respect to r_vector.
1446  // -1.0 since r_vector = CS_data_atom_xyz - ma_source_atom_xyz.
1447  numeric::xyzVector<core::Real> const f2_calc_chem_shift = -1.0 * get_delta_magnetic_anisotropy_deriv(CS_data_atom_xyz, ma_source_atom_xyz, ma_source_base_coordinate_matrix, ma_source_rsd_CS_params, ma_source_realatomdata_index);
1448 
1449  numeric::xyzVector<core::Real> const f1_calc_chem_shift = cross( f2_calc_chem_shift, CS_data_atom_xyz);
1450 
1451  //RIGHT NOW NUMERICAL AND ANALYTICAL DERIV DOESN'T AGREE NEAR zero due to switch in H5'/H5'' atom pairs.
1452  //DO TO: Include a fade function to fix this!
1453  f1+= 2.0*(calc_chem_shift-act_exp_chem_shift)*(f1_calc_chem_shift); //Convert deriv_vector of calc_chem_shift to deriv_vector of chemical_shift_energy
1454  f2+= 2.0*(calc_chem_shift-act_exp_chem_shift)*(f2_calc_chem_shift); //Convert deriv_vector of calc_chem_shift to deriv_vector of chemical_shift_energy
1455 
1456 
1457  }
1458  }
1459 
1460  }
1461 
1462 
1463 
1464  ///////////////////////////////////////////////////////////////////////////////
1465  void
1467  id::AtomID const & atom_id,
1468  pose::Pose const & pose,
1469  kinematics::DomainMap const &,
1470  EnergyMap const & weights,
1471  Vector & F1,
1472  Vector & F2
1473  ) const
1474  {
1475 
1476  using namespace conformation;
1477 
1478  Size const seq_num = atom_id.rsd();
1479  Size const atomno = atom_id.atomno();
1480 
1481  conformation::Residue const & rsd = pose.residue( seq_num );
1482  if ( !rsd.is_RNA() ) return;
1483 
1484  //OK two possible force contributions (the two should be mutually exclusive!).
1485  //i. Contain chemical_shift data on this atom (non-polar protons)
1486  //ii. Atom is source of ring_current B-field (most base heavy-atoms) or the magnetic_anisotropy B-field (all base heavy-atoms)
1487 
1488  //Vector f1( 0.0 ),f2( 0.0 );
1489 
1490  numeric::xyzVector<core::Real> f1(0.0, 0.0, 0.0);
1491  numeric::xyzVector<core::Real> f2(0.0, 0.0, 0.0);
1492 
1493  if(false){
1494  std::cout << "eval_atom_derivative() for name_from_aa(rsd.aa())= " << name_from_aa(rsd.aa());
1495  std::cout << " | seq_num= " << seq_num;
1496  std::cout << " | atomno= " << atomno;
1497  std::cout << " | atom_name= " << rsd.atom_name(atomno);
1498  std::cout << std::endl;
1499  }
1500 
1501  if(atom_has_exp_chemical_shift_data(rsd, atomno)){
1502 
1503  get_deriv_for_chemical_shift_data_atom(pose, rsd, atomno, f1, f2);
1504 
1505  }
1506 
1507 
1508  if(atomno == chi1_torsion_atom_index( rsd )) { //first chi1_torsion_atom serves as 'proxy' for the ring_center!
1509 
1510  get_ring_current_deriv_for_src_base(pose, rsd, atomno, f1, f2);
1511 
1512  get_magnetic_anisotropy_deriv_for_src_base(pose, rsd, atomno, f1, f2);
1513 
1514  }
1515 
1516 
1517  //I don't fully understand this. But if I get_deriv at the actual location of the ma source atoms, then the analytical/numeric deriv ratio at the first chi1_torsion_atom will be slightly by ~5%-35% percent. To get the correct derivative, need get deriv at the chi1_torsion_atom instead (see above).
1518 
1519  //if(Is_magnetic_anisotropy_source_atom(rsd, atomno)){
1520  //get_deriv_for_magnetic_anisotropy_src_atom(pose, rsd, atomno, f1, f2);
1521  //}
1522 
1523 
1524  F1 += weights[ rna_chem_shift ] * f1;
1525  F2 += weights[ rna_chem_shift ] * f2;
1526 
1527 
1528  } // eval atom derivative
1529 
1530 
1531 
1532 } // chemical_shift
1533 } // rna
1534 } // scoring
1535 } // core