Rosetta 3.5
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
CrossPeak.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 FragmentSampler.cc
11 /// @brief ab-initio fragment assembly protocol for proteins
12 /// @detailed
13 /// Contains currently: Classic Abinitio
14 ///
15 ///
16 /// @author Oliver Lange
17 
18 // Unit Headers
21 
22 // Package Headers
26 
27 // Project Headers
28 #include <core/chemical/AA.hh>
32 // Utility headers
33 
34 #include <ObjexxFCL/format.hh>
35 #include <ObjexxFCL/string.functions.hh>
36 
37 // AUTO-REMOVED #include <utility/string_util.hh>
38 #include <utility/exit.hh>
39 // #include <utility/vector1.fwd.hh>
40 // #include <utility/pointer/ReferenceCount.hh>
41 // #include <numeric/numeric.functions.hh>
42 #include <basic/prof.hh>
43 #include <basic/Tracer.hh>
44 #include <basic/options/option.hh>
45 // #include <core/options/keys/abinitio.OptionKeys.gen.hh>
46 // #include <core/options/keys/run.OptionKeys.gen.hh>
47 //#include <core/options/keys/templates.OptionKeys.gen.hh>
48 
49 //// C++ headers
50 #include <iostream>
51 #include <cstdlib>
52 #include <string>
53 
54 #include <utility/vector1.hh>
55 
56 //Auto Headers
57 #include <cmath>
58 
59 static basic::Tracer tr("protocols.noesy_assign.crosspeaks");
60 static basic::Tracer tr_labels("protocols.noesy_assign.crosspeaks.labels");
61 
62 using core::Real;
63 using namespace core;
64 using namespace basic;
65 
66 
67 namespace protocols {
68 namespace noesy_assign {
69 
70 std::set< core::id::NamedAtomID > CrossPeak::unknown_resonances_;
71 
72 CrossPeak::Spin::Spin( Real freq ) : freq_ ( freq ) {}
76  core::Size ct( 1 );
77  for ( SpinAssignments::const_iterator it = assignments_.begin(); it != assignments_.end(); ++it ) {
78  if ( assignment == *it ) return ct;
79  ++ct;
80  }
81  return 0;
82 }
83 
84 CrossPeak::CrossPeak( Spin const& sp1, Spin const& sp2, Real strength ) :
85  proton1_( sp1 ),
86  proton2_( sp2 ),
87  volume_( strength ),
89  distance_bound_( 100 ), //what would be a good initial value? -1 ?
92  elimination_candidate_( false )
93 {}
94 
96  cumulative_peak_volume_( 1.0 ),
97  distance_bound_( 100 ),
98  eliminated_( NOT_ELIMINATED ),
99  eliminated_due_to_dist_violations_( false ),
100  elimination_candidate_( false )
101 {}
102 
104 
105 ///@detail use for reading of assignments from file
106 /// pass as spin1, spin2, label1, label2 (indices 1..4)
108 // std::cerr << "CrossPeak::add_full_assignment stubbed out " << res_ids[ 1 ] << std::endl;
109 // std::cerr << "run with 'ignore_assignments'" << std::endl;
110 // utility_exit_with_message( "stubbed function" );
111  Size ind1 = assign_spin( 1, res_ids );
112  Size ind2 = assign_spin( 2, res_ids );
113  assignments_.push_back( new PeakAssignment( this, ind1, ind2 ) );
114 
115  // for ( Size i = 1;
116  //need to find resonances in Spins and add them if they are still missing.
117  //get id for spin1 and spin2
118  //then make PeakAssignment() and add to assignments_
119 }
120 
121 bool CrossPeak::has_proton( core::Size select ) const {
122  return info( select ).proton_tolerance() < 99;
123 }
124 
125 ///@brief find all possible assignments based on chemical shifts and tolerances
127 
128  if ( proton1_.n_assigned() && proton2_.n_assigned() ) return; //if assignments are already present do nothing
129 
130  runtime_assert( proton1_.n_assigned() == proton2_.n_assigned() );
131  assign_spin( 1 );
132  assign_spin( 2 );
133 
134  Size const n_assigned_1( proton( 1 ).n_assigned() );
135  Size const n_assigned_2( proton( 2 ).n_assigned() );
136 
137  for ( Size ct1 = 1; ct1 <= n_assigned_1; ++ct1 ) {
138  for ( Size ct2 = 1; ct2 <= n_assigned_2; ++ct2 ) {
139  assignments_.push_back( new PeakAssignment( this, ct1, ct2 ) );
140  }
141  }
142  //write_to_stream( tr.Debug );
143  // tr.Debug << std::endl;
144 }
145 
146 void CrossPeak::print_peak_info( std::ostream& os ) const {
147  os << "peak: " << peak_id() << " ";
148  for ( Size i = 1; i<=2 ; i++ ) {
149  os << info( i ).main_atom();
150  if ( info( i ).has_label() ) os << "-" << info( i ).label_atom_type();
151  if ( i == 1 ) os << " <-> ";
152  }
153 }
154 
155 ///@brief assign protons based on chemical shifts and tolerances
156 void CrossPeak::assign_spin( Size iproton ) {
157  //base-class: disregard label
158  Real const my_freq( proton( iproton ).freq() );
159  Real const my_tolerance( info( iproton ).proton_tolerance() );
160  for ( ResonanceList::const_iterator it = resonances().begin(); it != resonances().end(); ++it ) {
161  // if ( std::abs( fold_resonance( it->second->freq(), iproton ) - my_freq ) < std::max( my_tolerance, it->second->error() ) ) {
162  if ( it->second->match( my_freq, my_tolerance, folder( iproton ) ) ) {
163  proton( iproton ).add_assignment( it->first );
164  }
165  }
166 }
167 
168 ///@brief assign protons ass pre-determined
170  Size ind = proton( iproton ).assignment_index( res_id[ iproton ] );
171  if ( ind ) return ind;
172  proton( iproton ).add_assignment( res_id[ iproton ] );
173  return proton( iproton ).n_assigned();
174 }
175 
177  for ( Size i=1; i<=digits; ++i ) {
178  d*=10;
179  }
180  d = floor( d + 0.5 );
181  for ( Size i=1; i<=digits; ++i ) {
182  d/=10;
183  }
184  return d;
185 }
186 
187 void
191  pose::Pose const& pose,
192  pose::Pose const& centroid_pose,
193  core::Size normalization,
194  core::Real padding,
195  bool fa_only
196 ) const {
197  core::Size const round_digits( 2 );
198  using namespace core::scoring::constraints;
200  core::Real inv_weight( sqrt( 1.0*normalization )/params.cst_strength_ );
201 
202  FuncOP func( new BoundFunc(1.5,
203  round(distance_bound()+padding,round_digits),
204  round(inv_weight,round_digits),
205  "automatic NOE Peak "+ObjexxFCL::string_of( peak_id() )+" "+filename()+" Volume: "+ObjexxFCL::string_of( volume() )
206  )
207  );
208 
209  using namespace basic::options;
210  using namespace basic::options::OptionKeys;
211  bool const map_to_CEN( params.map_to_cen_atom_ );
212  // tr.Debug << "MAPPING TO " << ( map_to_CEN ? "CEN-ATOM" : "C-BETA" ) << std::endl;
213 
214  QualityClass const qc( quality_class() );
215  Real min_vc = params.min_volume_;
216  if ( qc == HI_NEAR_UNAMBIG ) {
217  min_vc = std::max( min_vc, 0.1 );
218  }
219 
220  Size ct_ambiguous( 0 );
221  PeakAssignments::const_iterator first_valid = end();
222  for ( PeakAssignments::const_iterator it = begin(); it != end(); ++it ) {
223  if ( (*it)->normalized_peak_volume() <= min_vc ) continue; //not enough contribution
224  if ( !ct_ambiguous ) first_valid = it;
225  ++ct_ambiguous;
226  }
227 
228  if ( qc == HI_NEAR_UNAMBIG || qc == HI_UNAMBIG ) {
229  runtime_assert( ct_ambiguous < 2 );
230  }
231 
232  if ( ct_ambiguous > 1 ) {
233  /// create Ambiguous constraint with BoundFunc describing the whole thing...
235  my_fa_cst = new AmbiguousNMRConstraint( func );
236 
238  my_cen_cst = new AmbiguousNMRConstraint( func );
239 
240  core::Size n( n_assigned() );
241  //mjo commenting out 'sd' because it is unused and causes a warning
242  //core::Real sd( 1.0/params.cst_strength_ );
243  core::Real eff_single_dist( pow( pow( distance_bound(), -6 ) / n, -1.0/6 ) ); //assuming equal contribution of all which is of course wrong
244  core::Real cum_new_distance( 0 );
245  core::Size max_maps=0;
246  // add individual constraints --- their potential does not matter ... it is ignored in evaluation...
247  for ( PeakAssignments::const_iterator it = first_valid; it != end(); ++it ) {
248  if ( (*it)->normalized_peak_volume() <= min_vc ) continue; //not enough contribution
249  AmbiguousNMRDistanceConstraintOP new_cst( (*it)->create_constraint( pose ) );
250  my_fa_cst->add_individual_constraint( new_cst );
251  fa_cst = my_fa_cst;
252  if ( !fa_only ) {
253  Size number_of_maps; //are 0, 1 or 2 sidechains replaced by CB
254  if ( map_to_CEN ) {
255  my_cen_cst->add_individual_constraint( new_cst->map_to_CEN( pose, centroid_pose, number_of_maps, "CEN" ) );
256  max_maps = std::max( number_of_maps, max_maps );
257  } else {
258  my_cen_cst->add_individual_constraint( new_cst->map_to_CEN( pose, centroid_pose, number_of_maps, "CB" ) );
259  cum_new_distance += pow( (eff_single_dist + params.centroid_mapping_distance_padding_*number_of_maps )*pow( new_cst->multiplicity(), 1.0/6 ), -6 );
260  }
261  }
262  }
263  if ( !fa_only ) {
264  Real mapped_upl;
265  Real mapped_inv_weight;
266  if ( map_to_CEN ) {
267  mapped_upl = distance_bound() + max_maps; //add 0, 1 or 2 A
268  mapped_inv_weight = inv_weight * pow( 2.0, double(max_maps) );
269  } else {
270  mapped_upl = pow( cum_new_distance, -1.0/6 );
271  mapped_inv_weight = inv_weight;
272  }
273  cen_cst = my_cen_cst->clone( new BoundFunc( 1.5,
274  round(mapped_upl,round_digits),
275  round(mapped_inv_weight,round_digits),
276  "CEN mapped automatic NOE: Peak "+ ObjexxFCL::string_of( peak_id() )
277  ) );
278  }
279  } else { // not ambiguous
280  if ( first_valid == end() ) return;
281  AmbiguousNMRDistanceConstraintOP my_fa_cst = (*first_valid)->create_constraint( pose, func ); //first one should be only one,
282  fa_cst = my_fa_cst;
283  if ( !fa_only ) {
284  Size number_of_maps; //are 0, 1 or 2 sidechains replaced by CB
285  core::Size n( n_assigned() );
286  core::Real eff_single_dist( pow( pow( distance_bound(), -6 ) / n, -1.0/6 ) ); //assuming equal contribution of all which is of course wrong
287  core::Real cum_new_distance( 0 );
288  ConstraintOP my_cen_cst;
289  core::Real mapped_upl;
290  core::Real mapped_inv_weight;
291  if ( map_to_CEN ) {
292  my_cen_cst= my_fa_cst->map_to_CEN( pose, centroid_pose, number_of_maps, "CEN" );
293  mapped_upl = distance_bound() + number_of_maps;
294  mapped_inv_weight = inv_weight*pow( 2.0, double(number_of_maps) );
295  } else {
296  my_cen_cst= my_fa_cst->map_to_CEN( pose, centroid_pose, number_of_maps, "CB" );
297  cum_new_distance += pow( (eff_single_dist + params.centroid_mapping_distance_padding_*number_of_maps )*pow( my_fa_cst->multiplicity(), 1.0/6 ), -6 );
298  mapped_upl = pow( cum_new_distance, -1.0/6 );
299  mapped_inv_weight = inv_weight;
300  }
301  std::string const comment( "CEN mapped automatic NOE: Peak "+ ObjexxFCL::string_of( peak_id() ) );
302  cen_cst = my_cen_cst->clone( new BoundFunc( 1.5, round(mapped_upl,round_digits), round(mapped_inv_weight,round_digits), comment ) );
303  }
304  // tr.Trace << "constraint for " << peak_id() << " finished " << std::endl;
305  }
306 }
307 
308 Real sigmoid( Real x, Real tau, Real m, int sign = 1 ) {
309  if ( sign > 0 ) {
310  return 1.0/(1+exp(-1.0/tau*5.0*(x-m)));
311  }
312  return 1.0-1./(1+exp(-1.0/tau*5.0*(x-m)));
313 }
314 
316  Real max_vc_cs( 0.0 );
317  Real max_vc_sym( 0.0 );
318  Real max_vc( 0.0 );
319  Real const overall_vc( cumulative_peak_volume() );
321  for ( const_iterator ait = begin(); ait != end(); ++ait ) {
322  if ( max_vc < (*ait)->normalized_peak_volume() ) {
323  max_vc = (*ait)->normalized_peak_volume();
324  max_vc_sym = (*ait)->symmetry_compliance();
325  max_vc_cs = (*ait)->chemshift_compliance();
326  }
327  }
328  utility::vector1< Real > const& w( params.prob_sigmoid_w_ );
329  utility::vector1< Real > const& tau( params.prob_sigmoid_tau_ );
330  utility::vector1< Real > const& m( params.prob_sigmoid_m_ );
331  Real s[6];
332  s[1] = sigmoid( max_vc_cs, tau[1], m[1], 1);
333  s[2] = sigmoid( max_vc_sym, tau[2], m[2], 1);
334  s[3] = -sigmoid( max_vc_sym, tau[3], m[3], -1);
335  s[4] = sigmoid( max_vc, tau[4], m[4], 1 );
336  s[5] = -sigmoid( overall_vc, tau[5], m[5], -1 );
337  return (w[1]*s[1]+w[2]*s[2]+w[3]*s[3]+w[4]*s[4]+w[5]*s[5]+0.4)/1.6;
338 }
339 
341  Real viol( 100000 );
342  QualityClass pclass( quality_class() );
343  for ( const_iterator ait = begin(); ait != end(); ++ait ) {
344  Real const vc( (*ait)->normalized_peak_volume() );
345  if ( pclass==HI_UNAMBIG && vc < 0.1 ) continue;
346  if ( pclass<=MED_AMBIG && vc < 0.01 ) continue;
347  if ( viol > (*ait)->native_distance_viol() ) viol=(*ait)->native_distance_viol();
348  }
349  return viol;
350 }
351 
353  char const strings[][50] = {"HI_UNAMBIG", "HI_NEAR_UNAMBIG", "HI_AMBIG", "MED_AMBIG", "MED_UNAMBIG", "LOW_AMBIG" };
354  return strings[ quality_class() ];
355 }
356 
358  Size count_vc_0p1( 0 );
359  Size count_vc_0p01( 0 );
360  for ( const_iterator ait = begin(); ait != end(); ++ait ) {
361  Real const vc( (*ait)->normalized_peak_volume() );
362  if ( vc > 0.1 ) ++count_vc_0p1;
363  if ( vc > 0.01 ) ++count_vc_0p01;
364  }
365  enum ProbClass {
366  HI = 0,
367  MED,
368  LOW
369  };
370 
371  Real const prob( probability() );
372  ProbClass pclass;
374  if ( prob > params.prob_level_[1] ) {
375  pclass = HI;
376  } else if ( prob > params.prob_level_[2] ) {
377  pclass = MED;
378  } else {
379  pclass = LOW;
380  }
381 
382  if ( pclass == HI ) {
383  if ( count_vc_0p01 == 1 ) {
384  return HI_UNAMBIG;
385  } else if ( count_vc_0p1 == 1 ) {
386  return HI_NEAR_UNAMBIG;
387  } else {
388  return HI_AMBIG;
389  }
390  } else if ( pclass == MED ) {
391  if ( count_vc_0p1 == 1 || count_vc_0p01 == 1 ) {
392  return UNAMBIG_MED_PROB;
393  }
394  return MED_AMBIG;
395  } else {
396  return BAD_LOW_PROB;
397  }
398 
399 }
400 
402  Real max_volume( 0.0 );
403  for ( const_iterator ait = begin(); ait != end(); ++ait ) {
404  max_volume= std::max( max_volume, (*ait)->normalized_peak_volume() );
405  }
406  return max_volume;
407 }
408 
409 #if 0
411 CrossPeak::create_constraint( pose::Pose const& pose, core::Size normalization ) const {
412 
413 
414  basic::ProfileThis doit( basic::NOESY_ASSIGN_CP_GEN_CST );
415 
417  core::Real inv_weight( sqrt( 1.0*normalization )/params.cst_strength_ );
418  core::Size const round_digits( 2 );
419  core::scoring::constraints::FuncOP func( new core::scoring::constraints::BoundFunc( 1.5, round(distance_bound(),round_digits), round(inv_weight,round_digits), "automatic NOE Peak "+ObjexxFCL::string_of( peak_id() )+" "+filename() ) );
420 
421  Size ct_ambiguous( 0 );
422  for ( PeakAssignments::const_iterator it = begin(); it != end(); ++it ) {
423  if ( (*it)->normalized_peak_volume() <= params.min_volume_ ) continue; //not enough contribution
424  ++ct_ambiguous;
425  }
426 
427  if ( ct_ambiguous > 1 ) {
430 
431  for ( PeakAssignments::const_iterator it = begin(); it != end(); ++it ) {
432  if ( (*it)->normalized_peak_volume() <= params.min_volume_ ) continue; //not enough contribution
433  constraint->add_individual_constraint( (*it)->create_constraint( pose ) );
434  }
435  return constraint;
436  } else {
437  for ( PeakAssignments::const_iterator it = begin(); it != end(); ++it ) {
438  if ( (*it)->normalized_peak_volume() <= params.min_volume_ ) continue; //not enough contribution
439  return (*it)->create_constraint( pose, func ); //first one should be only one,
440  }
441  }
442  return NULL; //never reached
443 }
444 
446 CrossPeak::create_centroid_constraint(
447  pose::Pose const& pose,
448  pose::Pose const& centroid_pose,
449  core::Size normalization
450  ) const {
451  using namespace core::scoring::constraints;
452  core::Size const round_digits(2);
453 
454  PeakAssignmentParameters const& params( *PeakAssignmentParameters::get_instance() );
455  core::Real inv_weight( round( sqrt( 1.0*normalization )/params.cst_strength_, round_digits ) );
456 
457  // if ( ct_ambiguous>1 ) {
458  AmbiguousNMRConstraintOP constraint =
460  ( new BoundFunc( 1.5, round( distance_bound(), round_digits), inv_weight, "automatic NOE Peak "+ObjexxFCL::string_of( peak_id() ) ) );
461  core::Size n( n_assigned() );
462  core::Real sd( 1.0/params.cst_strength_ );
463  core::Real eff_single_dist( pow( pow( distance_bound(), -6 ) / n, -1.0/6 ) ); //assuming equal contribution of all which is of course wrong
464  core::Real cum_new_distance( 0 );
465  for ( PeakAssignments::const_iterator it = begin(); it != end(); ++it ) {
466  if ( (*it)->normalized_peak_volume() <= params.min_volume_ ) continue; //not enough contribution
467  AmbiguousNMRDistanceConstraintOP new_cst( (*it)->create_constraint( pose ) );
468  Size number_of_maps; //are 0, 1 or 2 sidechains replaced by CB
469  constraint->add_individual_constraint( new_cst->map_to_CEN( pose, centroid_pose, number_of_maps, "CB" ) );
470  cum_new_distance += pow( (eff_single_dist + params.centroid_mapping_distance_padding_*number_of_maps )*pow( new_cst->multiplicity(), 1.0/6 ), -6 );
471  sd += params.centroid_mapping_distance_padding_*( pow( new_cst->multiplicity()-1, 1.0/6 ) );
472  }
473  return constraint->clone( new BoundFunc( 1.5, round( pow( cum_new_distance, -1.0/6 ), round_digits), inv_weight, "CB mapped automatic NOE: Peak "+ ObjexxFCL::string_of( peak_id() ) ) );
474  /// 10/22/2010 replace sd*inv_weight with inv_weight... centroid csts were generally underinv_weighted compared to fullatom...
475 // } else { //not ambiguous
476 // }
477 }
478 #endif
479 
480 ///@brief do we have a inter residue assignment with at least volume_threshold contribution ?
482  Size min_seq( 99999 );
483  for ( PeakAssignments::const_iterator it = begin(); it != end(); ++it ) {
484  if ( (*it)->normalized_peak_volume() <= volume_threshold ) continue; //not enough contribution
485  Size res1( (*it)->resid( 1 ) );
486  Size res2( (*it)->resid( 2 ) );
487  Size diff( res1 < res2 ? res2-res1 : res1-res2 );
488  min_seq = min_seq < diff ? min_seq : diff;
489  }
490  return min_seq;
491 }
492 
494  static std::string const str_distviol( "DistViol" );
495  static std::string const str_network( "Network" );
496  static std::string const str_minvol( "MinPeakVol");
497  static std::string const str_maxassign( "MaxAssign");
498  static std::string const empty_str( "" );
499  if ( eliminated_ == EL_DISTVIOL ) return str_distviol + " " + elimination_comment_;
500  if ( eliminated_ == EL_NETWORK ) return str_network;
501  if ( eliminated_ == EL_MINPEAKVOL ) return str_minvol;
502  if ( eliminated_ == EL_MAXASSIGN ) return str_maxassign;
503  return empty_str;
504 }
505 
506 bool CrossPeak::eliminated( bool recompute, bool do_not_compute ) const {
507  if ( recompute && !do_not_compute ) eliminated_ = eliminated_due_to_dist_violations_ ? EL_DISTVIOL : NOT_ELIMINATED;
508  //if dist_cut problem eliminated_ should already be set to false.
509  // tr.Trace << "elimination check for peak " << peak_id() << "...";
510  // if ( eliminated_ ) tr.Trace << "eliminated from cached value" << std::endl;
511  if ( eliminated_ ) return true;
512  if ( do_not_compute ) return false; //not eliminated as of now...
513 
515  bool min_peak_volume_reached( false );
516  for ( PeakAssignments::const_iterator it = begin(); it != end() && !min_peak_volume_reached ; ++it ) {
517  min_peak_volume_reached = (*it)->normalized_peak_volume() > params.min_volume_;
518  }
519 
520  eliminated_ = !min_peak_volume_reached ? EL_MINPEAKVOL : eliminated_;
521  // if ( eliminated_ ) tr.Trace << "eliminated (min_peak_volume)" << std::endl;
522  if ( eliminated_ ) return true;
523 
524  bool const too_many_assignments( assignments().size() > params.nmax_ );
525  eliminated_ = too_many_assignments ? EL_MAXASSIGN : eliminated_;
526  // if ( eliminated_ ) tr.Trace << "eliminated (too many assignments)" << std::endl;
527  if ( eliminated_ ) return true;
528 
529  //network anchoring
530  Real N_atom_sum( 0.0 );
531  Real N_res_sum( 0.0 );
532  for ( PeakAssignments::const_iterator it = begin(); it != end(); ++it ) {
533  Real vol( (*it)->normalized_peak_volume() );
534  N_atom_sum += vol * (*it)->network_anchoring();
535  N_res_sum += vol * (*it)->network_anchoring_per_residue();
536  }
537  bool pass_network_test( N_res_sum > params.network_reswise_high_ );
538  if ( !pass_network_test ) pass_network_test = N_res_sum >= params.network_reswise_min_ && N_atom_sum >= params.network_atom_min_;
539  eliminated_ = !pass_network_test ? EL_NETWORK : eliminated_;
540  // if ( eliminated_ ) tr.Trace << "eliminated (network)" << std::endl;
541 
542  if ( eliminated_ ) return true;
543  // tr.Trace << "passed" << std::endl;
544  return false;
545 }
546 
549  Size ct( 0 );
550  for ( PeakAssignments::const_iterator it = begin(); it != end(); ++it ) {
551  Real vol( (*it)->normalized_peak_volume() );
552  ct += vol > params.min_volume_;
553  }
554  return ct;
555 }
556 
558  distance_bound_ += offset;
559 }
560 
561 void CrossPeak::calibrate( PeakCalibrator const& calibrator, PeakCalibrator::TypeCumulator& calibration_types ) {
563  Real sum( 0.0 );
564  Size ct( 0 );
565  if ( volume_ <= 0.0 ) throw utility::excn::EXCN_BadInput("Peak intensity negative or zero for "+ObjexxFCL::string_of( peak_id_ ) );
566  for ( PeakAssignments::const_iterator it = begin(); it != end(); ++it ) {
567  CALIBRATION_ATOM_TYPE type1, type2;
568  type1 = (*it)->calibration_atom_type( 1 );
569  type2 = (*it)->calibration_atom_type( 2 );
570  calibration_types.set( type1 );
571  calibration_types.set( type2 );
572  Real const cal( sqrt( calibrator( type1 ) * calibrator( type2 ) ) );
573  Real vol( (*it)->normalized_peak_volume() );
574  Real int_factor(1.0);
575  int_factor*=resonances()[ (*it)->resonance_id( 1 ) ].intensity();
576  int_factor*=resonances()[ (*it)->resonance_id( 2 ) ].intensity();
577  sum += (vol > params.min_volume_ ? vol : 0 ) / cal / int_factor;
578  ct += vol > params.min_volume_;
579  }
580  if ( ct > 0 ) distance_bound_ = pow( sum*volume_, -1.0/6.0 );
581  else distance_bound_ = 0.0;
582 
583  core::Real max_dist( info( 1 ).max_noe_distance() );
584  if ( max_dist > 0.01 ) {
585  distance_bound_ = std::min( distance_bound_, max_dist );
586  }
587 }
588 
589 ///@brief assign protons ass pre-determined
590 Size CrossPeak3D::assign_spin( Size iproton, Size res_id[] ) {
591  Size ind = CrossPeak::assign_spin( iproton, res_id );
592  if ( iproton == 1 && ind > label( iproton ).n_assigned() ) label( iproton ).add_assignment( res_id[ iproton+2 ] );
593  return ind;
594 }
595 
597  if ( iproton == 2 ) CrossPeak::assign_spin( iproton ); //base-class: no label
598  else assign_labelled_spin( iproton );
599 }
600 
602  runtime_assert( has_label( iproton ));
603  Real const my_freq( proton( iproton ).freq() );
604  Real const my_label_freq( label( iproton ).freq() );
605  Real const my_tolerance( info( iproton ).proton_tolerance() );
606  Real const my_label_tolerance( info( iproton ).label_tolerance() );
607 
608 
609  /// if we have pseudo 4D spectrum we speed things up a bit by filtering out non-protons here
610  if ( my_tolerance > 99 ) {
611  for ( ResonanceList::const_iterator it = resonances().begin(); it != resonances().end(); ++it ) {
612  // if ( std::abs( fold_resonance( it->second->freq(), iproton + 2 ) - my_label_freq ) < std::max( my_label_tolerance, it->second->error() ) ) {
613  if ( it->second->match( my_label_freq, my_label_tolerance, folder( iproton+2 ) ) ) {
614  //now find all proton-resonances that are bound to this label atom
615  core::Size resid( it->second->resid() );
616  std::string const& label_name( it->second->name() );
617  ResonanceList::Resonances const& residue_list( resonances().resonances_at_residue( resid ) );
618  for ( ResonanceList::Resonances::const_iterator rit = residue_list.begin(); rit != residue_list.end(); ++rit ) {
619  if ( (*rit)->name()[ 0 ]=='Q' || (*rit)->name().find("H") != std::string::npos ) {
620  // tr.Debug << "resid: " << resid<< " test label: " << label_name << " with proton " << (*rit)->name() << std::endl;
621  try {
622  std::string possible_label( info( iproton ).
623  label_atom_name( (*rit)->name(), resonances().aa_from_resid( resid ) ) );
624  //tr.Debug << "found possible label " << possible_label << std::endl;
625  if ( possible_label == label_name ) {
626  label( iproton ).add_assignment( it->first );
627  proton( iproton ).add_assignment( (*rit)->label() );
628  //we have found a proton that can be attached to our label
629  }
630  } catch ( EXCN_UnknownAtomname& exception ) {
631  continue;
632  }
633  } // if rit is proton
634  } // for rit
635  } // if matched resonance
636  }// all resonances
637  } else {
638  for ( ResonanceList::const_iterator it = resonances().begin(); it != resonances().end(); ++it ) {
639 
640  /// if we have pseudo 4D spectrum we speed things up a bit by filtering out non-protons here
641  // if ( my_tolerance > 99 && ( it->second->freq() > 13.0 && info( iproton ).main_atom() == "H" ) ) continue;
642 
643  // if ( std::abs( fold_resonance( it->second->freq(), iproton ) - my_freq ) < std::max( my_tolerance, it->second->tolerance() ) ) {
644  if ( it->second->match( my_freq, my_tolerance, folder( iproton ) ) ) {
645  Size resid( it->second->atom().rsd() );
646  //maybe also map resonance by resid?
647  try {
648  id::NamedAtomID atomID( info( iproton ).label_atom_name( it->second->atom().atom(), resonances().aa_from_resid( resid ) ), resid );
649  Resonance const& label_reso ( resonances()[ atomID ] );
650  // if ( std::abs( fold_resonance( label_reso.freq(), iproton+2 ) - my_label_freq ) < my_label_tolerance ) {
651  if ( label_reso.match( my_label_freq, my_label_tolerance, folder( iproton+2 ) ) ) {
652  proton( iproton ).add_assignment( it->first );
653  label( iproton ).add_assignment( label_reso.label() );
654  }
655  } catch ( EXCN_UnknownResonance& exception ) {
656  if ( !unknown_resonances_.count( exception.atom() ) ) {
657  unknown_resonances_.insert( exception.atom() );
658  exception.show( tr.Warning );
659  tr.Warning << " as label for atom " << it->second->atom().atom() << " " << resonances().aa_from_resid( resid ) << std::endl;
660  // if ( tr.Debug.visible() ) exception.show( tr.Debug );
661  }
662  continue; //if no label is known we don't assign this proton
663  } catch ( EXCN_UnknownAtomname& exception ) { //this happens if we try to assign a proton that can't have a label: i.e., a H in a HCH spectrum
664  //tr_labels.Trace << "cannot find label atom for resid: " + it->second->atom().atom() + " " + ObjexxFCL::string_of( resid ) + " --- ignore proton assignment" << std::endl;
665  //if ( tr.Debug.visible() ) exception.show( tr.Debug );
666  continue;
667  }
668  }
669  }
670  }
671 }
672 // void CrossPeak::invalidate_assignment( Size iassignment ) {
673 // proton( 1 ).invalidate_assignment_by_nr( iassignment );
674 // proton( 2 ).invalidate_assignment_by_nr( iassignment );
675 // if ( has_label( 1 ) ) label( 1 ).invalidate_assignment_by_nr( iassignment );
676 // if ( has_label( 2 ) ) label( 2 ).invalidate_assignment_by_nr( iassignment );
677 // }
678 
679 CrossPeak3D::CrossPeak3D( Spin const& sp1, Spin const& sp2, Spin const& label1, Real strength ) :
680  CrossPeak( sp1, sp2, strength ),
681  label1_( label1 )
682 {}
683 
686 
687 CrossPeak4D::CrossPeak4D( Spin const& sp1, Spin const& sp2, Spin const& label1, Spin const& label2, Real strength ) :
688  CrossPeak3D( sp1, sp2, label1, strength ),
689  label2_( label2 )
690 {}
691 
694 
696  assign_labelled_spin( iproton );
697 }
698 
699 Size CrossPeak4D::assign_spin( Size iproton, Size res_id[] ) {
700  Size ind = CrossPeak::assign_spin( iproton, res_id );
701  if ( ind > label( iproton ).n_assigned() ) label( iproton ).add_assignment( res_id[ iproton+2 ] );
702  return ind;
703 }
704 
705 // void CrossPeak::read_from_stream( std::istream& is ) {
706 // Real freq;
707 // is >> freq;
708 // proton1_ = Spin( freq );
709 // if ( has_label( 1 ) ) {
710 // is >> freq;
711 // label( 1 ) = Spin( freq );
712 // }
713 
714 // is >> freq;
715 // proton2_ = Spin( freq );
716 // if ( has_label( 2 ) ) {
717 // is >> freq;
718 // label( 2 ) = Spin( freq );
719 // }
720 
721 // Size number;
722 // char letter;
723 // is >> number >> letter; //no idea what these mean ...it reads now 3 U or 4 U
724 // is >> volume_;
725 // Real error_of_strength; //... ???
726 // is >> error_of_strength;
727 
728 // char letter_e;
729 // Size number_0;
730 // is >> letter_e;
731 // is >> number_0;
732 // add_assignment_from_stream( is );
733 // }
734 
735 // void CrossPeak::add_assignment_from_stream( std::istream& is ) {
736 // Size id;
737 // is >> id;
738 // if ( id ) proton1_.add_assignment( id );
739 // if ( has_label( 1 ) ) {
740 // is >> id;
741 // if ( id ) label( 1 ).add_assignment( id );
742 // }
743 
744 // is >> id;
745 // if ( id ) proton2_.add_assignment( id );
746 // if ( has_label( 2 ) ) {
747 // is >> id;
748 // if ( id ) label( 2 ).add_assignment( id );
749 // }
750 // }
751 
752 
753 // void CrossPeak::write_to_stream( std::ostream& os ) const {
754 // os << ObjexxFCL::fmt::F( 8, 3, proton1_.freq() ) << " ";
755 // if ( has_label( 1 ) ) {
756 // os << ObjexxFCL::fmt::F( 8, 3, label( 1 ).freq() ) << " ";
757 // }
758 
759 // os << ObjexxFCL::fmt::F( 8, 3, proton2_.freq() ) << " ";
760 // if ( has_label( 2 ) ) {
761 // os << ObjexxFCL::fmt::F( 8, 3, label( 2 ).freq() ) << " ";
762 // }
763 
764 // os << ObjexxFCL::fmt::E( 10, 3, strength_ ) << " " << ObjexxFCL::fmt::E( 10, 3, 0.0 ) << " ";
765 
766 // Size assignments_written( 0 );
767 // // while ( assignments_written < proton1_.n_assigned() ) {
768 // for ( PeakAssignments::const_iterator it = assignments_.begin(); it != assignments_.end(); ++it ) {
769 // ++assignments_written;
770 // if ( assignments_written > 1 ) os << std::endl << " ";
771 // for ( Size i=1; i<=2; i++ ) {
772 // os << ObjexxFCL::fmt::RJ( 6, (*it)->resonance_id( i ) ) << " ";
773 // if ( has_label( i ) ) {
774 // os << ObjexxFCL::fmt::RJ( 6, (*it)->label_resonance_id( i ) << " ";
775 // }
776 // }
777 // }
778 // }
779 
780 
781 
782 } //noesy_assign
783 } //devel