Rosetta 3.5
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
Ramachandran2B.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/Ramachandran2B.cc
11 /// @brief Neighbor Dependent Ramachandran potential class implementation
12 /// @author Guoli Wang
13 /// @author Amelie Stein (amelie.stein@ucsf.edu) Oct 2012 -- rama2b lookup table for loop modeling
14 
15 // Unit Headers
17 
18 // Package Headers
19 #include <core/scoring/Energies.hh>
21 // AUTO-REMOVED #include <core/scoring/ProteinTorsion.hh>
22 
23 // Project Headers
25 #include <core/pose/Pose.hh>
26 #include <basic/database/open.hh>
27 #include <basic/options/option.hh>
28 #include <basic/Tracer.hh>
29 
30 // Numeric Headers
31 #include <numeric/angle.functions.hh>
32 #include <numeric/interpolation/periodic_range/half/interpolation.hh>
33 #include <numeric/random/random.hh>
34 
35 // Utility Headers
36 #include <utility/io/izstream.hh>
37 
38 #if defined(WIN32) || defined(__CYGWIN__)
39  #include <ctime>
40 #endif
41 
42 // AS -- to get access to get_torsion_bin()
44 
45 // option key includes
46 
47 #include <basic/options/keys/score.OptionKeys.gen.hh>
48 #include <basic/options/keys/corrections.OptionKeys.gen.hh>
49 #include <basic/options/keys/in.OptionKeys.gen.hh>
50 #include <basic/options/keys/OptionKeys.hh>
51 
52 //Auto Headers
53 #include <utility/vector1.hh>
54 #include <ObjexxFCL/FArray2A.hh>
55 
56 
57 
58 using namespace ObjexxFCL;
59 
60 namespace core {
61 namespace scoring {
62 
63 // @brief Auto-generated virtual destructor
64 Ramachandran2B::~Ramachandran2B() {}
65 
66 basic::Tracer T("core.scoring.Ramachandran2B");
67 
68 Real const Ramachandran2B::binw_( 10.0 );
69 //AS
70 Real const Ramachandran2B::rama_sampling_thold_(0.00075 ); // only sample torsions with Rama prob above this value -- note that values are directly copied from the Ramachandran.cc implementation, might need tweaking
71 Real const Ramachandran2B::rama_sampling_factor_( 10.0 ); // factor for increased precision of Rama sampling table
72 ObjexxFCL::FArray4D< Real > Ramachandran2B::left_ram_probabil_( Ramachandran2B::n_phi_, Ramachandran2B::n_psi_, Ramachandran2B::n_aa_, Ramachandran2B::n_aa_ );
73 ObjexxFCL::FArray4D< Real > Ramachandran2B::right_ram_probabil_( Ramachandran2B::n_phi_, Ramachandran2B::n_psi_, Ramachandran2B::n_aa_, Ramachandran2B::n_aa_ );
74 
75 Ramachandran2B::Ramachandran2B() :
76  ram_energ_( n_phi_, n_psi_, n_aa_, 0.0 ),
77  ram_entropy_( n_aa_, 0.0 ),
78  ram_energ_left_( n_phi_, n_psi_, n_aa_, n_aa_, 0.0 ),
79  ram_entropy_left_( n_aa_, n_aa_, 0.0 ),
80  ram_energ_right_( n_phi_, n_psi_, n_aa_, n_aa_, 0.0 ),
81  ram_entropy_right_( n_aa_, n_aa_, 0.0 ),
82  rama_score_limit_( 20 ) // customizable in the future, possibly by command line flags.
83 {
84  read_rama();
85 }
86 
87 
88 ///////////////////////////////////////////////////////////////////////////////
89 
90 /// @brief evaluate rama score for each (protein) residue and store that score
91 /// in the pose.energies() object
92 void
94  pose::Pose & pose,
95  ScoreFunction const & scorefxn
96 ) const
97 {
98  if ( scorefxn.has_zero_weight( rama ) ) return; // unnecessary, righ?
99 
100  //double rama_sum = 0.0;
101 
102  // in pose mode, we use fold_tree.cutpoint info to exclude terminus
103  // residues from rama calculation. A cutpoint could be either an artificial
104  // cutpoint such as loop cutpoint or a real physical chain break such as
105  // multiple-chain complex. For the artificial cutpoint, we may need to
106  // calculate rama scores for cutpoint residues, but for the real chain break
107  // cutpoint, we don't want to do that. So here we first loop over all the
108  // residue in the protein and exclude those ones which are the cutpoints.
109  // Then we loop over the cutpoint residues and add rama score for residues
110  // at artificial cutpoints, i.e., cut_weight != 0.0, which means that
111  // jmp_chainbreak_score is also calculated for this cutpoint. Note that the
112  // default value for cut_weight here is dependent on whether
113  // jmp_chainbreak_weight is set. This is to ensure that rama score for
114  // termini residues are not calculated when jmp_chainbreak_weight is 0.0,
115  // e.g normal pose docking.
116 
117  int const total_residue = pose.total_residue();
118 
119  // retrieve cutpoint info // apl do we actually need this data?
120  // if so, Pose must provide it 'cause we're offing all global data
121  //
122  //kinematics::FoldTree const & fold_tree(
123  // pose.fold_tree() );
124  //int const n_cut( fold_tree.num_cutpoint() );
125 
126  //FArray1D< Real > cut_weight( n_cut,
127  // scorefxns::jmp_chainbreak_weight == 0.0 ? 0.0 : 1.0 ); // apl need to handle
128 
129  //if( cut_weight.size1() == scorefxns::cut_weight.size1() )
130  // cut_weight = scorefxns::cut_weight;
131 
132  // exclude chain breaks
133 
134  Energies & pose_energies( pose.energies() );
135 
136  for ( int ii = 1; ii <= total_residue; ++ii )
137  {
138  if ( pose.residue(ii).is_protein() && ! pose.residue(ii).is_terminus() )
139  {
140  Real rama_score,dphi,dpsi;
141  eval_rama_score_residue(pose.residue(ii), pose.residue(ii-1).aa(), pose.residue(ii+1).aa(), rama_score, dphi, dpsi);
142  T << "Rama:eval_all: residue " << ii << " " << pose.residue(ii).name() <<
143  " " << ii-1 << " " << pose.residue(ii-1).name() << " " << ii+1 << " " <<
144  pose.residue(ii+1).name() << " = " << rama_score << std::endl;
145  pose_energies.onebody_energies( ii )[rama] = rama_score;
146  }
147  }
148 }
149 
150 
151 ///////////////////////////////////////////////////////////////////////////////
152 void
154 {}
155 
156 
157 ///////////////////////////////////////////////////////////////////////////////
158 void
160  conformation::Residue const & rsd,
161  Real & rama,
162  Real & drama_dphi,
163  Real & drama_dpsi
164 ) const
165 {
166  using namespace numeric;
167 
168  //assert( pose.residue(res).is_protein() );
169  assert( rsd.is_protein() );
170 
171  Real const phi
172  ( nonnegative_principal_angle_degrees( rsd.mainchain_torsion(1)));
173  Real const psi
174  ( nonnegative_principal_angle_degrees( rsd.mainchain_torsion(2)));
175 
176  if ( phi == 0.0 || psi == 0.0 || rsd.is_terminus() ) { // begin or end of chain
177  rama = 0.0;
178  drama_dphi = 0.0;
179  drama_dpsi = 0.0;
180  return;
181  }
182 
183  eval_rama_score_residue( rsd.aa(), phi, psi, rama, drama_dphi, drama_dpsi );
184 }
185 
186 ///////////////////////////////////////////////////////////////////////////////
187 // modified by GL
188 void
190  conformation::Residue const &center,
191  chemical::AA const left_aa,
192  chemical::AA const right_aa,
193  Real & rama,
194  Real & drama_dphi,
195  Real & drama_dpsi
196 ) const
197 {
198  using namespace numeric;
199 
200  assert( center.is_protein() );
201 
202  Real const phi
203  ( nonnegative_principal_angle_degrees( center.mainchain_torsion(1)));
204  Real const psi
205  ( nonnegative_principal_angle_degrees( center.mainchain_torsion(2)));
206 
207  if ( phi == 0.0 || psi == 0.0 ) { // begin or end of chain
208  rama = 0.0;
209  drama_dphi = 0.0;
210  drama_dpsi = 0.0;
211  return;
212  }
213 
214  if( ! basic::options::option[ basic::options::OptionKeys::score::ramaneighbors ] ) {
215  eval_rama_score_residue( center.aa(), phi, psi, rama, drama_dphi, drama_dpsi );
216  } else {
217  //if(left.seqpos() == center.seqpos()) {
218  // Ramachandran::RamaE_Upper(center, right_aa, drama_dphi, drama_dpsi);
219  //} else if(right.seqpos() == center.seqpos()) {
220  // Ramachandran::RamaE_Lower(center, left_aa, drama_dphi, drama_dpsi);
221  //} else {
222  Real rama_L(0.0), drama_dphi_L(0.0), drama_dpsi_L(0.0);
223  Real rama_R(0.0), drama_dphi_R(0.0), drama_dpsi_R(0.0);
224  Real rama_0(0.0), drama_dphi_0(0.0), drama_dpsi_0(0.0);
225  rama_L = RamaE_Lower(center, left_aa, drama_dphi_L, drama_dpsi_L);
226  rama_R = RamaE_Upper(center, right_aa, drama_dphi_R, drama_dpsi_R);
227  rama_0 = RamaE(center, drama_dphi_0, drama_dpsi_0);
228 
229  rama = rama_L + rama_R - rama_0;
230  drama_dphi = drama_dphi_L + drama_dphi_R - drama_dphi_0;
231  drama_dpsi = drama_dpsi_L + drama_dpsi_R - drama_dpsi_0;
232  //}
233  }
234 }
235 
236 void
238  Real const phi,
239  Real const psi,
240  Real & rama,
241  Real & drama_dphi,
242  Real & drama_dpsi,
243  Real const entropy,
244  FArray2A< Real > const & rama_for_res
245 ) const
246 {
247  using namespace numeric::interpolation::periodic_range::half;
248  Real interp_E = bilinearly_interpolated( phi, psi, binw_, n_phi_, rama_for_res, drama_dphi, drama_dpsi );
249  // rama = IdealizeRamaEnergy(ram_entropy_(center.aa(), leftIndex, rightIndex), interp_E, drama_dphi, drama_dpsi);
250  rama = entropy + interp_E;
251  // std::cout << "Rama::eval_res: " << interp_E << " rama " << rama << std::endl;
252 
253  if ( ! basic::options::option[basic::options::OptionKeys::corrections::score::rama_not_squared] ) {
254  if ( rama > 1.0 ) {
255  Real rama_squared = rama * rama;
256  if ( rama_squared > rama_score_limit_ ) {
257  drama_dphi = 0.0;
258  drama_dpsi = 0.0;
259  rama = rama_score_limit_;
260  } else {
261  drama_dphi *= 2.0 * rama;
262  drama_dpsi *= 2.0 * rama;
263  rama = rama_squared;
264  }
265  }
266  }
267 
268  // std::cout << " rama: " << rama << " dphi " << drama_dphi << " dpsi " << drama_dpsi << std::endl;
269 }
270 
271 // end modification
272 
273 ///////////////////////////////////////////////////////////////////////////////
274 // modified by GL according to Andrew's suggestion
275 Real
277  conformation::Residue const &rsd,
278  chemical::AA const &neighbor
279 ) const
280 {
281  Real drama_dphi, drama_dpsi;
282  return RamaE_Lower( rsd, neighbor, drama_dphi, drama_dpsi );
283 }
284 
285 Real
287  conformation::Residue const &rsd,
288  chemical::AA const &neighbor,
289  Real & drama_dphi,
290  Real & drama_dpsi
291 ) const
292 {
293  using namespace numeric;
294  using namespace basic::options;
295  using namespace basic::options::OptionKeys;
296 
297  assert( rsd.is_protein() );
298 
299  Real const phi
300  ( nonnegative_principal_angle_degrees( rsd.mainchain_torsion(1)));
301  Real const psi
302  ( nonnegative_principal_angle_degrees( rsd.mainchain_torsion(2)));
303 
304  if ( phi == 0.0 || psi == 0.0 ) { // begin or end of chain
305  return 0.0;
306  }
307 
308  // if neighbor independent protocol is selected, return 0.0
309  if( ! option[ score::ramaneighbors ] ) {
310  return 0.0;
311  }
312 
313  FArray2A< Real >::IR const zero_index( 0, n_phi_ - 1);
314  FArray2A< Real > const rama_for_res( ram_energ_left_(1, 1, rsd.aa(), neighbor), zero_index, zero_index );
315  Real entropy = ram_entropy_left_(rsd.aa(), neighbor);
316 
317  Real rama;
318  IdealizeRamaEnergy( phi, psi, rama, drama_dphi, drama_dpsi, entropy, rama_for_res );
319  return rama;
320 }
321 Real
323  conformation::Residue const &rsd,
324  chemical::AA const &neighbor
325 ) const
326 {
327  Real drama_dphi, drama_dpsi;
328  return RamaE_Upper( rsd, neighbor, drama_dphi, drama_dpsi );
329 }
330 
331 Real
333  conformation::Residue const &rsd,
334  chemical::AA const &neighbor,
335  Real & drama_dphi,
336  Real & drama_dpsi
337 ) const
338 {
339  using namespace numeric;
340 
341  assert( rsd.is_protein() );
342 
343  Real const phi
344  ( nonnegative_principal_angle_degrees( rsd.mainchain_torsion(1)));
345  Real const psi
346  ( nonnegative_principal_angle_degrees( rsd.mainchain_torsion(2)));
347 
348  if ( phi == 0.0 || psi == 0.0 ) { // begin or end of chain
349  return 0.0;
350  }
351 
352  // if neighbor independent protocol is selected, return 0.0
353  if( ! basic::options::option[ basic::options::OptionKeys::score::ramaneighbors ] )
354  {
355  return 0.0;
356  }
357 
358  FArray2A< Real >::IR const zero_index( 0, n_phi_ - 1);
359  FArray2A< Real > const rama_for_res( ram_energ_right_(1, 1, rsd.aa(), neighbor), zero_index, zero_index );
360  Real entropy = ram_entropy_right_(rsd.aa(), neighbor);
361 
362  Real rama;
363  IdealizeRamaEnergy( phi, psi, rama, drama_dphi, drama_dpsi, entropy, rama_for_res );
364  return rama;
365 }
366 
367 Real
369  conformation::Residue const &rsd
370 ) const
371 {
372  Real drama_dphi(0.0), drama_dpsi(0.0);
373  return RamaE( rsd, drama_dphi, drama_dpsi );
374 }
375 
376 Real
378  conformation::Residue const &rsd,
379  Real & drama_dphi,
380  Real & drama_dpsi
381 ) const
382 {
383 
384  using namespace numeric;
385 
386  assert( rsd.is_protein() );
387 
388  Real const phi
389  ( nonnegative_principal_angle_degrees( rsd.mainchain_torsion(1)));
390  Real const psi
391  ( nonnegative_principal_angle_degrees( rsd.mainchain_torsion(2)));
392 
393  if ( phi == 0.0 || psi == 0.0 ) { // begin or end of chain
394  return 0.0;
395  }
396 
397  Real ramaE(0.0);
398  eval_rama_score_residue( rsd.aa(), phi, psi, ramaE, drama_dphi, drama_dpsi );
399  return ramaE;
400 }
401 
402 ///////////////////////////////////////////////////////////////////////////////
403 ///
404 Real
406  AA const res_aa,
407  Real const phi,
408  Real const psi
409 ) const
410 {
411 
412  Real rama, drama_dphi, drama_dpsi;
413  eval_rama_score_residue( res_aa, phi, psi, rama, drama_dphi, drama_dpsi );
414  return rama;
415 }
416 
417 ///////////////////////////////////////////////////////////////////////////////
418 ///
419 void
421  AA const res_aa,
422  Real const phi,
423  Real const psi,
424  Real & rama,
425  Real & drama_dphi,
426  Real & drama_dpsi
427 ) const
428 {
429  using namespace numeric;
430 
431  FArray2A< Real >::IR const zero_index( 0, n_phi_ - 1);
432  FArray2A< Real > const rama_for_res( ram_energ_(1, 1, res_aa ), zero_index, zero_index );
433  Real entropy = ram_entropy_(res_aa);
434 
435  IdealizeRamaEnergy( phi, psi, rama, drama_dphi, drama_dpsi, entropy, rama_for_res );
436 }
437 
438 
439 // Guoli Wang
440 void
442 {
443  using namespace basic::options;
444 
445  using namespace basic::options::OptionKeys;
446 
447  int aa_num( 0 ), aa_num_left( 0 ), aa_num_right( 0 );
448  int phi_bin( 0 ), psi_bin( 0 ), ss_type( 0 );
449  int tCounts( 0 );
450  Real tProb( 0.0 ), tEnergy( 0.0 );
451 
452  Size line_count( 0 );
453 
454 
455  //utility::io::izstream iunit;
456 #ifndef WIN32
457 #ifndef __CYGWIN__
458  clock_t starttime = clock();
459 #endif
460 #endif
461  std::string energyFileName = basic::options::option[ in::file::rama2b_map ]().name() ; // "wrapHDPprobs36.both";
462  T << "Read in ramachandran map: " << energyFileName << std::endl;
463  utility::io::izstream iRamaEnergy;
464  basic::database::open( iRamaEnergy, energyFileName );
465  while( ! iRamaEnergy.eof() ) {
466  ++line_count;
467  iRamaEnergy >> aa_num >> aa_num_left >> aa_num_right >> ss_type >> phi_bin >> psi_bin >> tCounts >> tProb >> tEnergy;
468  // std::cout << " aa_num " << aa_num << " aa_num_left " << aa_num_left << " aa_num_right " << aa_num_right << " ss_type " << ss_type <<
469  // " phi_bin " << phi_bin << " psi_bin " << psi_bin << " tProb " << tProb << " tEnergy " << tEnergy << std::endl;
470  if(aa_num > n_aa_) continue;
471 
472  int phiIndex = phi_bin / 10 + 1;
473  int psiIndex = psi_bin / 10 + 1;
474  Real entropy = -1.0 * tProb * tEnergy;
475 
476  if( aa_num_left == nullaa && aa_num_right == nullaa ) {
477  ram_energ_( phiIndex, psiIndex, aa_num ) = tEnergy;
478  ram_entropy_( aa_num ) += entropy;
479  } else if( aa_num_left != nullaa ) {
480  ram_energ_left_( phiIndex, psiIndex, aa_num, aa_num_left ) = tEnergy;
481  ram_entropy_left_( aa_num, aa_num_left ) += entropy;
482  left_ram_probabil_( phiIndex, psiIndex, aa_num_left, aa_num ) = tProb;
483  } else if( aa_num_right != nullaa ) {
484  ram_energ_right_( phiIndex, psiIndex, aa_num, aa_num_right ) = tEnergy;
485  ram_entropy_right_( aa_num, aa_num_right ) += entropy;
486  right_ram_probabil_( phiIndex, psiIndex, aa_num, aa_num_right ) = tProb;
487 
488  }
489  }
490 
491  iRamaEnergy.close();
492 #ifndef WIN32
493 #ifndef __CYGWIN__
494  clock_t stoptime = clock();
495  T << "Reading Rama from database took " << ((double) stoptime - starttime)/CLOCKS_PER_SEC << " seconds" << std::endl;
496 #endif
497 #endif
498 }
499 
500  ///////////////////////////////////////////////////////////////////////////////
501  /// Initialize the table holding the sample-able torsion space for each residue and its left neighbor
502  /// with each torsion given indices proportionate to its probability
503  /// @author Amelie Stein amelie.stein@ucsf.edu
504  /// @brief based on the corresponding function for the Ramachandran class, but with adapted dimensions to accommodate the two neighbors
505  void
506  Ramachandran2B::init_rama_sampling_table_left( const char torsion_bin ) // to be adapted !!
507  {
508  //rama_sampling_table_.resize(n_aa_);
510  current_rama_sampling_table.resize(n_aa_);
511  //int ss_type=3; // WARNING -- data for neighbor-dependent Rama is only available for 3 in the current file (Rama08.dat) -- and thus currently this information isn't even encoded in the rama_probabil_ table
512  FArray2A< Real >::IR const zero_index( 0, n_phi_ - 1);
513  for (int left_aa=1; left_aa<=n_aa_; left_aa++) { // loop over all residue types
514  current_rama_sampling_table[left_aa].resize(n_aa_);
515  for (int aa=1; aa<=n_aa_; aa++) { // loop over all residue types
516  current_rama_sampling_table[left_aa][aa].resize(n_aa_);
517  FArray2A< Real > const rama_for_res( left_ram_probabil_(1, 1, left_aa, aa), zero_index, zero_index ); // is this correct? Why are we not accessing each one for the specific phi/psi combination?
518  Size max_allowed = n_phi_ * n_psi_;
519  Size actual_allowed = 0;
520  Real min_val = 1.0; // minimum probability (above rama_sampling_thold_) observed for this residue
521  Real max_val = 0.0; // maximum probability (above rama_sampling_thold_) observed for this residue
522  utility::vector1< utility::vector1< Real> > res_torsions( max_allowed ); // double vector of allowed torsions for this residue
523  utility::vector1< Real > res_probs( max_allowed ); // rama probs of allowed torsions for this residue (coupled to res_torsions by index)
524  // current_rama_sampling_table[left_aa][aa][right_aa].resize(max_allowed); // I think this is resized later anyway
525  for (int i=0; i<n_phi_; i++) {
526  for (int j=0; j<n_psi_; j++) {
527  Real res_prob = rama_for_res(i,j);
528 
529  //std::cerr << res_prob << std::endl;
530 
531  if ( res_prob > rama_sampling_thold_ ) {
532  actual_allowed++;
533  if (res_prob < min_val) min_val = res_prob;
534  else if (res_prob > max_val) max_val = res_prob;
535  //std::cout << res_prob << std::endl;
536  //res_probs[actual_allowed] = res_prob;
537 
538  utility::vector1< Real > torsion(2);
539  Real cur_phi, cur_psi;
540  if (i <= n_phi_ / 2) {
541  cur_phi = i;
542  }
543  else {
544  cur_phi = 0 - (n_phi_ - i);
545  }
546  if (j <= n_psi_ / 2) {
547  cur_psi = j;
548  }
549  else {
550  cur_psi = 0 - (n_psi_ - j);
551  }
552 
553 
554  char cur_tb = ' ';
555  if (torsion_bin != 'X')
556  cur_tb = core::conformation::get_torsion_bin(cur_phi * 10, cur_psi * 10); // AS -- how can we get the factor properly / without hard-coding? - also: this takes very long...
557  if (torsion_bin == 'X' || cur_tb == torsion_bin) {
558  actual_allowed++;
559  res_probs[actual_allowed] = res_prob;
560  torsion[1] = static_cast <Real> (/*i*/ cur_phi * binw_); // phi
561  torsion[2] = static_cast <Real> (/*j*/ cur_psi * binw_); // psi
562  res_torsions[actual_allowed] = torsion;
563  }
564  //rama_sampling_table_[aa][++actual_allowed] = torsion;
565  //} else {
566  //std::cerr << "warning -- discarding phi/psi " << cur_phi << "/" << cur_psi << " because they're not in torsion bin " << torsion_bin << std::endl;
567  }
568  }
569  }
570 
571  /* not sure how to adapt this...
572  if( ((int)aa < (int)1) || ((int)aa > (int)current_rama_sampling_table.size()) ){
573  std::cerr << "AA exceeded size of rama_sampling_table_ AA=" + ObjexxFCL::string_of( aa ) + " size()=" + ObjexxFCL::string_of( current_rama_sampling_table.size() );
574  continue; // Avoid death.
575  }
576  */
577 
578 
579 
580  // now populate the rama_sampling_table_ so the torsions are given index space proporionate to their probs
581  current_rama_sampling_table[left_aa][aa].resize(Size(actual_allowed * (max_val / min_val) * rama_sampling_factor_));
582  Size index=0; // to increment the index into the aa's rama_sampling_table_ vector
583  //std::cout << "for aa " << aa << ":" << std::endl;
584  for (Size tor = 1; tor <= actual_allowed; tor++) {
585  Size n_indices = Size(( res_probs[tor] / min_val ) * rama_sampling_factor_);
586  //std::cout << "n_indices for torsion " << tor << ": " << n_indices << std::endl;
587  for (Size ind=1; ind<=n_indices; ind++) {
588  index++;
589  if( (int(index) < 1) || (int(index) > (int)current_rama_sampling_table[left_aa][aa].size()) ){
590  std::cerr << "index exceeded size of rama_sampling_table_[aa] index=" +
591  ObjexxFCL::string_of( (index) ) +
592  " rama_sampling_table_[aa].size()=" +
593  ObjexxFCL::string_of( current_rama_sampling_table[left_aa][aa].size() ) +
594  " AA=" + ObjexxFCL::string_of( aa );
595 
596  continue; // avoid certain death - we dont yet understand why its failing here occasionally
597  }
598  if( ((int)tor < 1) || ((int)tor > (int)res_torsions.size()) ){
599  std::cerr << "tor exceeded size of rama_sampling_table_[aa] index=" +
600  ObjexxFCL::string_of( tor ) +
601  " res_torsions.size()=" + ObjexxFCL::string_of( res_torsions.size() ) +
602  " AA=" + ObjexxFCL::string_of( aa );
603  continue; // avoid certain death - we dont yet understand why its failing here occasionally
604  }
605 
606  current_rama_sampling_table[left_aa][aa][index] = res_torsions[tor];
607  }
608  }
609  current_rama_sampling_table[left_aa][aa].resize(index);
610  //std::cerr << "populating (left) table for torsion bin " << torsion_bin << " and " << AA(left_aa) << " " << AA(aa) << " -- " << index << " entries" << std::endl; // AS debug
611 
612  } // loop over aa
613  } // loop over left_aa
614 
615  if (torsion_bin == 'X') {
616  left_rama_sampling_table_ = current_rama_sampling_table;
617  }
618  core::Size tb_index = get_torsion_bin_index(torsion_bin);
619  //std::cerr << "storing table for torsion bin " << torsion_bin << " --> " << tb_index << std::endl;
620  if (left_rama_sampling_table_by_torsion_bin_.size() < tb_index)
622  //std::cerr << "table resized" << std::endl;
623  left_rama_sampling_table_by_torsion_bin_[tb_index] = current_rama_sampling_table;
624 
625  }
626 
627  ///////////////////////////////////////////////////////////////////////////////
628  /// Sample phi/psi torsions with probabilities proportionate to their
629  /// Ramachandran probabilities
630  /// Note -- this function had previously required that the option
631  /// loops::nonpivot_torsion_sampling be active. This function now
632  /// performs a just-in-time check to initialize these tables the first
633  /// time they are requested -- To properly multi-thread this code, the
634  /// function should nab a mutex so that no two threads try to execute
635  /// the code at once.
636  void
638  AA const left_aa,
639  AA const pos_aa,
640  Real & phi,
641  Real & psi
642  ) const {
643 
644  if ( left_rama_sampling_table_.size() == 0 ) {
645  /// Danger -- not threadsafe.
646  const_cast< Ramachandran2B * > (this)->init_rama_sampling_table_left('X');
647  }
648 
649  Size n_torsions = left_rama_sampling_table_[left_aa][pos_aa].size();
650  Size index = numeric::random::random_range(1, n_torsions);
651 
652  // following lines set phi and set to values drawn proportionately from Rama space
653  // plus or minus uniform noise equal to half the bin width.
654  phi = left_rama_sampling_table_[left_aa][pos_aa][index][1] +
655  (numeric::random::uniform() * binw_ * 0.5 * (numeric::random::uniform() < 0.5 ? -1 : 1));
656  psi = left_rama_sampling_table_[left_aa][pos_aa][index][2] +
657  (numeric::random::uniform() * binw_ * 0.5 * (numeric::random::uniform() < 0.5 ? -1 : 1));
658  }
659 
660 
661 
662 
663  ///////////////////////////////////////////////////////////////////////////////
664  /// Initialize the table holding the sample-able torsion space for each residue and its right neighbor
665  /// with each torsion given indices proportionate to its probability
666  /// @author Amelie Stein amelie.stein@ucsf.edu
667  /// @brief based on the corresponding function for the Ramachandran class, but with adapted dimensions to accommodate the two neighbors
668  void
670  {
671  //rama_sampling_table_.resize(n_aa_);
673  current_rama_sampling_table.resize(n_aa_);
674  //int ss_type=3; // WARNING -- data for neighbor-dependent Rama is only available for 3 in the current file (Rama08.dat) -- and thus currently this information isn't even encoded in the rama_probabil_ table
675  FArray2A< Real >::IR const zero_index( 0, n_phi_ - 1);
676  for (int aa=1; aa<=n_aa_; aa++) { // loop over all residue types
677  current_rama_sampling_table[aa].resize(n_aa_);
678  for (int right_aa=1; right_aa<=n_aa_; right_aa++) { // loop over all residue types
679  FArray2A< Real > const rama_for_res( right_ram_probabil_(1, 1, aa, right_aa), zero_index, zero_index ); // is this correct? Why are we not accessing each one for the specific phi/psi combination?
680  Size max_allowed = n_phi_ * n_psi_;
681  Size actual_allowed = 0;
682  Real min_val = 1.0; // minimum probability (above rama_sampling_thold_) observed for this residue
683  Real max_val = 0.0; // maximum probability (above rama_sampling_thold_) observed for this residue
684  utility::vector1< utility::vector1< Real> > res_torsions( max_allowed ); // double vector of allowed torsions for this residue
685  utility::vector1< Real > res_probs( max_allowed ); // rama probs of allowed torsions for this residue (coupled to res_torsions by index)
686  // current_rama_sampling_table[left_aa][aa][right_aa].resize(max_allowed); // I think this is resized later anyway
687  for (int i=0; i<n_phi_; i++) {
688  for (int j=0; j<n_psi_; j++) {
689  Real res_prob = rama_for_res(i,j);
690 
691  //std::cerr << res_prob << std::endl;
692 
693  if ( res_prob > rama_sampling_thold_ ) {
694  actual_allowed++;
695  if (res_prob < min_val) min_val = res_prob;
696  else if (res_prob > max_val) max_val = res_prob;
697  //std::cout << res_prob << std::endl;
698  //res_probs[actual_allowed] = res_prob;
699 
700  utility::vector1< Real > torsion(2);
701  Real cur_phi, cur_psi;
702  if (i <= n_phi_ / 2) {
703  cur_phi = i;
704  }
705  else {
706  cur_phi = 0 - (n_phi_ - i);
707  }
708  if (j <= n_psi_ / 2) {
709  cur_psi = j;
710  }
711  else {
712  cur_psi = 0 - (n_psi_ - j);
713  }
714 
715  char cur_tb = ' ';
716  if (torsion_bin != 'X')
717  cur_tb = core::conformation::get_torsion_bin(cur_phi * 10, cur_psi * 10); // AS -- how can we get the factor properly / without hard-coding? - also: this takes very long...
718  if (torsion_bin == 'X' || cur_tb == torsion_bin) {
719  actual_allowed++;
720  res_probs[actual_allowed] = res_prob;
721  torsion[1] = static_cast <Real> (/*i*/ cur_phi * binw_); // phi
722  torsion[2] = static_cast <Real> (/*j*/ cur_psi * binw_); // psi
723  res_torsions[actual_allowed] = torsion;
724  }
725  //rama_sampling_table_[aa][++actual_allowed] = torsion;
726  //} else {
727  //std::cerr << "warning -- discarding phi/psi " << cur_phi << "/" << cur_psi << " because they're not in torsion bin " << torsion_bin << std::endl;
728  }
729  }
730  }
731 
732  /* not sure how to adapt this...
733  if( ((int)aa < (int)1) || ((int)aa > (int)current_rama_sampling_table.size()) ){
734  std::cerr << "AA exceeded size of rama_sampling_table_ AA=" + ObjexxFCL::string_of( aa ) + " size()=" + ObjexxFCL::string_of( current_rama_sampling_table.size() );
735  continue; // Avoid death.
736  }
737  */
738 
739 
740 
741  // now populate the rama_sampling_table_ so the torsions are given index space proporionate to their probs
742  current_rama_sampling_table[aa][right_aa].resize(Size(actual_allowed * (max_val / min_val) * rama_sampling_factor_));
743  Size index=0; // to increment the index into the aa's rama_sampling_table_ vector
744  //std::cout << "for aa " << aa << ":" << std::endl;
745  for (Size tor = 1; tor <= actual_allowed; tor++) {
746  Size n_indices = Size(( res_probs[tor] / min_val ) * rama_sampling_factor_);
747  //std::cout << "n_indices for torsion " << tor << ": " << n_indices << std::endl;
748  for (Size ind=1; ind<=n_indices; ind++) {
749  index++;
750  if( (int(index) < 1) || (int(index) > (int)current_rama_sampling_table[aa][right_aa].size()) ){
751  std::cerr << "index exceeded size of rama_sampling_table_[aa] index=" +
752  ObjexxFCL::string_of( (index) ) +
753  " rama_sampling_table_[aa].size()=" +
754  ObjexxFCL::string_of( current_rama_sampling_table[aa][right_aa].size() ) +
755  " AA=" + ObjexxFCL::string_of( aa );
756 
757  continue; // avoid certain death - we dont yet understand why its failing here occasionally
758  }
759  if( ((int)tor < 1) || ((int)tor > (int)res_torsions.size()) ){
760  std::cerr << "tor exceeded size of rama_sampling_table_[aa] index=" +
761  ObjexxFCL::string_of( tor ) +
762  " res_torsions.size()=" + ObjexxFCL::string_of( res_torsions.size() ) +
763  " AA=" + ObjexxFCL::string_of( aa );
764  continue; // avoid certain death - we dont yet understand why its failing here occasionally
765  }
766 
767  current_rama_sampling_table[aa][right_aa][index] = res_torsions[tor];
768  }
769  }
770  current_rama_sampling_table[aa][right_aa].resize(index);
771 
772  //std::cerr << "populating (right) table for torsion bin " << torsion_bin << " and " << AA(aa) << " " << AA(right_aa) << " -- " << index << " entries" << std::endl;
773 
774  // problem: some of these (highly specialized) bins are empty, but it can still happen that we request the respective bin
775  // -- workaround 1: use the data across all bins (X) instead
776  // -- workaround 2: use the minimum fraction from both the left and the right side, to make sure we don't run into this
777 
778 
779  } // loop over right_aa
780  } // loop over aa
781 
782  if (torsion_bin == 'X') {
783  right_rama_sampling_table_ = current_rama_sampling_table;
784  }
785  core::Size tb_index = get_torsion_bin_index(torsion_bin);
786  //std::cerr << "storing table for torsion bin " << torsion_bin << " --> " << tb_index << std::endl;
787  if (right_rama_sampling_table_by_torsion_bin_.size() < tb_index)
789  //std::cerr << "table resized" << std::endl;
790  right_rama_sampling_table_by_torsion_bin_[tb_index] = current_rama_sampling_table;
791  }
792 
793  ///////////////////////////////////////////////////////////////////////////////
794  /// Sample phi/psi torsions with probabilities proportionate to their
795  /// Ramachandran probabilities
796  /// Note -- this function had previously required that the option
797  /// loops::nonpivot_torsion_sampling be active. This function now
798  /// performs a just-in-time check to initialize these tables the first
799  /// time they are requested -- To properly multi-thread this code, the
800  /// function should nab a mutex so that no two threads try to execute
801  /// the code at once.
802  void
804  AA const pos_aa,
805  AA const right_aa,
806  Real & phi,
807  Real & psi
808  ) const {
809 
810  if ( right_rama_sampling_table_.size() == 0 ) {
811  /// Danger -- not threadsafe.
812  const_cast< Ramachandran2B * > (this)->init_rama_sampling_table_right('X');
813  }
814 
815  Size n_torsions = right_rama_sampling_table_[pos_aa][right_aa].size();
816  Size index = numeric::random::random_range(1, n_torsions);
817 
818  // following lines set phi and set to values drawn proportionately from Rama space
819  // plus or minus uniform noise equal to half the bin width.
820  phi = right_rama_sampling_table_[pos_aa][right_aa][index][1] +
821  (numeric::random::uniform() * binw_ * 0.5 * (numeric::random::uniform() < 0.5 ? -1 : 1));
822  psi = right_rama_sampling_table_[pos_aa][right_aa][index][2] +
823  (numeric::random::uniform() * binw_ * 0.5 * (numeric::random::uniform() < 0.5 ? -1 : 1));
824  }
825 
826 
828  {
829  return toupper(torsion_bin) - toupper('A') + 1;
830  }
831 
832  // just to avoid code duplication
833  void
835  {
836  const_cast< Ramachandran2B * > (this)->init_rama_sampling_table_left( 'X' ); // to allow wildcards in the torsion string, and to have "backup" data to access in case the selected bin is empty for a given combination (e.g., V-Y (G) doesn't have any entries, but if we filled it based on the right side we may request a G bin anyway)
837  const_cast< Ramachandran2B * > (this)->init_rama_sampling_table_left( 'A' );
838  const_cast< Ramachandran2B * > (this)->init_rama_sampling_table_left( 'B' );
839  const_cast< Ramachandran2B * > (this)->init_rama_sampling_table_left( 'E' );
840  const_cast< Ramachandran2B * > (this)->init_rama_sampling_table_left( 'G' );
841 
842  const_cast< Ramachandran2B * > (this)->init_rama_sampling_table_right( 'X' ); // to allow wildcards in the torsion string
843  const_cast< Ramachandran2B * > (this)->init_rama_sampling_table_right( 'A' );
844  const_cast< Ramachandran2B * > (this)->init_rama_sampling_table_right( 'B' );
845  const_cast< Ramachandran2B * > (this)->init_rama_sampling_table_right( 'E' );
846  const_cast< Ramachandran2B * > (this)->init_rama_sampling_table_right( 'G' );
847 
848  //std::cerr << " rama2b initialization by torsion bin done" << std::endl;
849 
850  }
851 
852 
853 
854  ///////////////////////////////////////////////////////////////////////////////
855  /// Sample phi/psi torsions with probabilities proportionate to their
856  /// Ramachandran probabilities -- this version performs lookup restricted to specified torsion bins
857  /// based on random_phipsi_from_rama and has the same issue for parallel running
858 
859  /// @author Amelie Stein (amelie.stein@ucsf.edu)
860  /// @date Fri May 11 15:52:01 PDT 2012
861  /// @details returns a random phi/psi combination within the given torsion bin -- WARNING: this will only work for the torsion bins that are currently implemented
862 
863  void
865  AA const left_aa,
866  AA const pos_aa,
867  Real & phi,
868  Real & psi,
869  char const torsion_bin
870  ) const
871  {
873  const_cast< Ramachandran2B * > (this)->init_rama_sampling_tables_by_torsion_bin(); // covers both left and righ
874  // not threadsafe either
875  }
876 
877  core::Size tb_index = get_torsion_bin_index(torsion_bin);
878 
879  Size n_torsions = left_rama_sampling_table_by_torsion_bin_[tb_index][left_aa][pos_aa].size();
880 
881 
882  //if (n_torsions == 0) { // debugging
883  // std::cerr << " error -- no entries found for (left) " << torsion_bin << " -- " << AA(left_aa) << " " << AA(pos_aa) << std::endl;
884  //}
885 
886  Size index = numeric::random::random_range(1, n_torsions);
887 
888  // following lines set phi and set to values drawn proportionately from Rama space
889  // plus or minus uniform noise equal to half the bin width.
890  phi = left_rama_sampling_table_by_torsion_bin_[tb_index][left_aa][pos_aa][index][1] +
891  (numeric::random::uniform() * binw_ * 0.5 * (numeric::random::uniform() < 0.5 ? -1 : 1));
892  psi = left_rama_sampling_table_by_torsion_bin_[tb_index][left_aa][pos_aa][index][2] +
893  (numeric::random::uniform() * binw_ * 0.5 * (numeric::random::uniform() < 0.5 ? -1 : 1));
894 
895  } // random_phipsi_from_rama_by_torsion_bin_left
896 
897  void
899  AA const pos_aa,
900  AA const right_aa,
901  Real & phi,
902  Real & psi,
903  char const torsion_bin
904  ) const
905  {
907  const_cast< Ramachandran2B * > (this)->init_rama_sampling_tables_by_torsion_bin(); // covers both left and righ
908  // not threadsafe either
909  }
910 
911  core::Size tb_index = get_torsion_bin_index(torsion_bin);
912 
913  Size n_torsions = right_rama_sampling_table_by_torsion_bin_[tb_index][pos_aa][right_aa].size();
914  //if (n_torsions == 0) { // debugging
915  // std::cerr << " error -- no entries found for (right) " << torsion_bin << " -- " << AA(pos_aa) << " " << AA(right_aa) << std::endl;
916  //}
917 
918  Size index = numeric::random::random_range(1, n_torsions);
919 
920  // following lines set phi and set to values drawn proportionately from Rama space
921  // plus or minus uniform noise equal to half the bin width.
922  phi = right_rama_sampling_table_by_torsion_bin_[tb_index][pos_aa][right_aa][index][1] +
923  (numeric::random::uniform() * binw_ * 0.5 * (numeric::random::uniform() < 0.5 ? -1 : 1));
924  psi = right_rama_sampling_table_by_torsion_bin_[tb_index][pos_aa][right_aa][index][2] +
925  (numeric::random::uniform() * binw_ * 0.5 * (numeric::random::uniform() < 0.5 ? -1 : 1));
926 
927  } // random_phipsi_from_rama_by_torsion_bin_right
928 
929 
930 
931  void
933  AA const left_aa,
934  AA const pos_aa,
935  std::map< char, core::Size > & tb_frequencies ) const
936  {
937  // check if the tables are initialized, and if not, do so
939  const_cast< Ramachandran2B * > (this)->init_rama_sampling_tables_by_torsion_bin();
940  tb_frequencies['A'] = left_rama_sampling_table_by_torsion_bin_[get_torsion_bin_index('A')][left_aa][pos_aa].size();
941  tb_frequencies['B'] = left_rama_sampling_table_by_torsion_bin_[get_torsion_bin_index('B')][left_aa][pos_aa].size();
942  tb_frequencies['E'] = left_rama_sampling_table_by_torsion_bin_[get_torsion_bin_index('E')][left_aa][pos_aa].size();
943  tb_frequencies['G'] = left_rama_sampling_table_by_torsion_bin_[get_torsion_bin_index('G')][left_aa][pos_aa].size();
944  tb_frequencies['X'] = left_rama_sampling_table_by_torsion_bin_[get_torsion_bin_index('X')][left_aa][pos_aa].size();
945  }
946 
947 
948  void
950  AA const pos_aa,
951  AA const right_aa,
952  std::map< char, core::Size > & tb_frequencies ) const
953  {
954  // check if the tables are initialized, and if not, do so
956  const_cast< Ramachandran2B * > (this)->init_rama_sampling_tables_by_torsion_bin();
957  tb_frequencies['A'] = right_rama_sampling_table_by_torsion_bin_[get_torsion_bin_index('A')][pos_aa][right_aa].size();
958  tb_frequencies['B'] = right_rama_sampling_table_by_torsion_bin_[get_torsion_bin_index('B')][pos_aa][right_aa].size();
959  tb_frequencies['E'] = right_rama_sampling_table_by_torsion_bin_[get_torsion_bin_index('E')][pos_aa][right_aa].size();
960  tb_frequencies['G'] = right_rama_sampling_table_by_torsion_bin_[get_torsion_bin_index('G')][pos_aa][right_aa].size();
961  tb_frequencies['X'] = right_rama_sampling_table_by_torsion_bin_[get_torsion_bin_index('X')][pos_aa][right_aa].size();
962  }
963 
964 
965 
966 
967 } // scoring
968 } // core