Rosetta 3.5
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
PeakAssignmentResidueMap.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
22 
23 // Package Headers
27 // Project Headers
28 
29 
30 // Utility headers
31 // AUTO-REMOVED #include <ObjexxFCL/format.hh>
32 
33 // AUTO-REMOVED #include <utility/string_util.hh>
34 // #include <utility/excn/Exceptions.hh>
35 // #include <utility/vector1.fwd.hh>
36 // #include <utility/pointer/ReferenceCount.hh>
37 // #include <numeric/numeric.functions.hh>
38 // #include <core/util/prof.hh>
39 #include <basic/Tracer.hh>
40 // #include <core/options/option.hh>
41 // #include <core/options/keys/abinitio.OptionKeys.gen.hh>
42 // #include <core/options/keys/run.OptionKeys.gen.hh>
43 //#include <core/options/keys/templates.OptionKeys.gen.hh>
44 #include <basic/prof.hh>
45 #include <ObjexxFCL/FArray2D.hh>
46 
47 //// C++ headers
48 #include <cstdlib>
49 #include <string>
50 
51 #ifdef WIN32
52 #include <iterator>
53 #endif
54 
56 #include <utility/vector1.hh>
57 
58 //Auto Headers
59 #include <cmath>
60 #include <set>
61 
62 
63 static basic::Tracer tr("protocols.noesy_assign.assignments");
64 
65 using core::Real;
66 using namespace core;
67 using namespace basic;
68 //using namespace core::options;
69 //using namespace OptionKeys;
70 
71 namespace protocols {
72 namespace noesy_assign {
73 
74 PeakAssignmentResidueMap::PeakAssignmentResidueMap() {}
75 PeakAssignmentResidueMap::~PeakAssignmentResidueMap() {}
76 
77 void PeakAssignmentResidueMap::add( PeakAssignmentOP const& assignment ) {
78  Size const res1( assignment->resid( 1 ) );
79  Size const res2( assignment->resid( 2 ) );
80  while ( residues_.size() < res1 ) {
81  residues_.push_back( PeakAssignmentMap() );
82  }
83  PeakAssignmentMap::iterator res2_entry( residues_[ res1 ].insert( PeakAssignmentMap::value_type( res2, PeakAssignments() ) ).first );
84  //res2_entry points now to an element in the res2 indexed map
85  res2_entry->second.push_back( assignment ); //currently no check for redundancy!
86 
87  while ( atoms_.size() < res1 ) {
88  atoms_.push_back( AtomList() );
89  }
90  while ( atoms_.size() < res2 ) {
91  atoms_.push_back( AtomList() );
92  }
93  atoms_[ res1 ].insert( assignment->atom( 1 ) );
94  atoms_[ res2 ].insert( assignment->atom( 2 ) );
95 
96 }
97 
98 void PeakAssignmentResidueMap::add_all_atoms( ResonanceList const& rslist ) {
99  for ( ResonanceList::const_iterator it = rslist.begin(); it != rslist.end(); ++it ) {
100  Size res1( it->second->resid() );
101  while ( atoms_.size() < res1 ) {
102  atoms_.push_back( AtomList() );
103  }
104  atoms_[ res1 ].insert( it->second->atom() );
105  }
106 }
107 ///@brief remove assignment...
108 void PeakAssignmentResidueMap::remove( PeakAssignment const& assignment ) {
109  Size const res1( assignment.resid( 1 ) );
110  Size const res2( assignment.resid( 2 ) );
111 
112  PeakAssignments& res2_entry( assignments( res1, res2 ) );
113  bool success( false );
114  for ( PeakAssignments::iterator it = res2_entry.begin(); !success && it != res2_entry.end(); ++it ) {
115  PeakAssignment const& assi( **it );
116  if ( assi == assignment ) {
117  res2_entry.erase( it );
118  success = true;
119  }
120  }
121  if ( !success ) {
122  throw EXCN_AssignmentNotFound( assignment, "remove: PeakAssignment not found -- no entry with exact assignment" );
123  }
124 }
125 
126 PeakAssignmentResidueMap::PeakAssignments const& PeakAssignmentResidueMap::assignments( core::Size res1, core::Size res2 ) const {
127  basic::ProfileThis doit( basic::NOESY_ASSIGN_NETWORK_FIND_RAW_ASSIGN );
128  if ( residues_.size() < res1 || res1 <= 0) {
129  throw EXCN_AssignmentNotFound( BOGUS_ASSIGNMENT, "PeakAssignment not found -- no entry with res1 " + ObjexxFCL::string_of( res1 ) );
130  }
131  PeakAssignmentMap::const_iterator res2_entry( residues_[ res1 ].find( res2 ) );
132  if ( res2_entry == residues_[ res1 ].end() ) {
133  throw EXCN_AssignmentNotFound( BOGUS_ASSIGNMENT, "PeakAssignment not found -- no entry with res2 " + ObjexxFCL::string_of( res2 ) );
134  }
135  return res2_entry->second;
136 }
137 
138 PeakAssignmentResidueMap::PeakAssignments& PeakAssignmentResidueMap::assignments( core::Size res1, core::Size res2 ) {
139  basic::ProfileThis doit( basic::NOESY_ASSIGN_NETWORK_FIND_RAW_ASSIGN );
140  if ( residues_.size() < res1 || res1 <= 0) {
141  throw EXCN_AssignmentNotFound( BOGUS_ASSIGNMENT, "PeakAssignment not found -- no entry with res1 " + ObjexxFCL::string_of( res1 ) );
142  }
143  PeakAssignmentMap::iterator res2_entry( residues_[ res1 ].find( res2 ) );
144  if ( res2_entry == residues_[ res1 ].end() ) {
145  throw EXCN_AssignmentNotFound( BOGUS_ASSIGNMENT, "PeakAssignment not found -- no entry with res2 " + ObjexxFCL::string_of( res2 ) );
146  }
147  return res2_entry->second;
148 }
149 
150 PeakAssignmentResidueMap::PeakAssignments& PeakAssignmentResidueMap::_assignments( core::Size res1, core::Size res2 ) {
151  basic::ProfileThis doit( basic::NOESY_ASSIGN_NETWORK_FIND_RAW_ASSIGN );
152  if ( residues_.size() < res1 || res1 <= 0 ) {
153  return BOGUS_ASSIGNMENTS;
154  }
155  PeakAssignmentMap::iterator res2_entry( residues_[ res1 ].find( res2 ) );
156  if ( res2_entry == residues_[ res1 ].end() ) {
157  return BOGUS_ASSIGNMENTS;
158  }
159  return res2_entry->second;
160 }
161 
162 bool PeakAssignmentResidueMap::has( core::Size res1, core::Size res2 ) {
163  return _assignments( res1, res2 ).size();
164 }
165 
166 void PeakAssignmentResidueMap::add( CrossPeakList const& cpl ) {
167  for ( CrossPeakList::CrossPeaks::const_iterator it = cpl.peaks().begin(); it != cpl.peaks().end(); ++it ) {
168  for ( CrossPeak::PeakAssignments::const_iterator ait = (*it)->assignments().begin(); ait != (*it)->assignments().end(); ++ait ) {
169  add( *ait );
170  }
171  }
172 }
173 
174 /*void PeakAssignmentResidueMap::invalidate_competitors_to_sequential_NOE( CrossPeakList& ) {
175  basic::ProfileThis doit( basic::NOESY_ASSIGN_NETWORK_INVALIDATE_SEQ_NOE );
176  for ( Size i=1; i<total_residue(); i++ ) {
177  tr.Info << "focus on sequential " << i << " " << i+1 << std::endl;
178  PeakAssignments sequential;
179  if ( has( i, i+1 )) {
180  PeakAssignments& sequential_1( assignments( i, i+1 ) );
181  copy( sequential_1.begin(), sequential_1.end(), back_inserter( sequential ) );
182  }
183  if ( has( i+1, i )) {
184  PeakAssignments& sequential_2( assignments( i+1, i ) );
185  copy( sequential_2.begin(), sequential_2.end(), back_inserter( sequential ) );
186  }
187  if ( has( i, i ) ) {
188  PeakAssignments& sequential_3( assignments( i, i ) );
189  copy( sequential_3.begin(), sequential_3.end(), back_inserter( sequential ) );
190  }
191  if ( sequential.size() > 1 ) tr.Info << "multiple sequential assignments found" << std::endl;
192  for ( PeakAssignments::iterator it = sequential.begin(); it!=sequential.end(); ++it ) {
193  CrossPeak& cp( (*it)->crosspeak() );
194  tr.Debug << "keep "
195  << (*it)->atom( 1 ) << "--"
196  << (*it)->atom( 2 ) << std::endl;
197  for ( CrossPeak::PeakAssignments::const_iterator cit = cp.assignments().begin(); cit!=cp.assignments().end(); ++cit ) {
198  if ( (**cit) == (**it) ) continue;
199  if ( tr.Debug.visible() ) {
200  tr.Debug << "remove "
201  << (*cit)->atom( 1 ) << "--"
202  << (*cit)->atom( 2 ) << std::endl;
203  }
204  //cp.invalidate_assignment( ai );
205  }
206  }
207  }
208 }
209 */
210 void PeakAssignmentResidueMap::check_for_symmetric_peaks( CrossPeakList& cpl, bool accumulate_symmetry ) {
211  for ( CrossPeakList::CrossPeaks::const_iterator it = cpl.peaks().begin(); it != cpl.peaks().end(); ++it ) {
212  CrossPeak::PeakAssignments const& assignments( (*it)->assignments() );
213  for ( CrossPeak::PeakAssignments::const_iterator ait = assignments.begin(); ait!=assignments.end(); ++ait ) {
214  PeakAssignment& current( **ait );
215  // tr.Debug << "sym-check: current " << current << " "
216  // << current.crosspeak().peak_id() << " " << current.crosspeak().filename() << std::endl;
217  //check if a symmetric partner for current exists
218  Size const res1( current.resid( 1 ) );
219  Size const res2( current.resid( 2 ) );
220  Real found( 0 );
221  PeakAssignments symmetric_candidates_inv( _assignments( res1, res2 ) );
222  if ( symmetric_candidates_inv.size() ) { //BOGUS_ASSIGNMENTS would be empty
223  for ( PeakAssignments::iterator sym_it = symmetric_candidates_inv.begin(); sym_it != symmetric_candidates_inv.end(); ++sym_it ) {
224  // tr.Debug << "sym-check: other " << **sym_it;
225  if ( (*sym_it)->is_symmetric_partner_of( current ) ) {
226  // tr.Debug << " MATCH 1 " << (*sym_it)->crosspeak().peak_id() << " " << (*sym_it)->crosspeak().filename() << std::endl;;
227  if ( !accumulate_symmetry ) {
228  // tr.Debug << std::endl;
229  found = 1;
230  break;
231  }
232  found += (*sym_it)->normalized_peak_volume();
233  }
234  // tr.Debug << std::endl;
235  }
236  }
237  PeakAssignments symmetric_candidates( _assignments( res2, res1 ) );
238  if ( symmetric_candidates.size() ) { //BOGUS_ASSIGNMENTS would be empty
239  for ( PeakAssignments::iterator sym_it = symmetric_candidates.begin(); sym_it != symmetric_candidates.end(); ++sym_it ) {
240  // tr.Debug << "sym-check: other " << **sym_it;
241  if ( (*sym_it)->is_symmetric_partner_of( current ) ) {
242  // tr.Debug << " MATCH 2 " << (*sym_it)->crosspeak().peak_id() << " " << (*sym_it)->crosspeak().filename() << std::endl;;
243  if ( !accumulate_symmetry ) {
244  found = 1;
245  // tr.Debug << std::endl;
246  break;
247  }
248  found += (*sym_it)->normalized_peak_volume();
249  }
250  // tr.Debug << std::endl;
251  }
252  }
253  current.set_symmetry( found );
254  }
255  }
256 }
257 
259 void retrieve_assignment( PeakAssignments const& list, Size resonance_id1, Size resonance_id2, PeakAssignments& intra_res_NOEs ) {
260  basic::ProfileThis doit( basic::NOESY_ASSIGN_NETWORK_RETRIEVE_ASSIGN );
261  for ( PeakAssignments::const_iterator it = list.begin(); it != list.end(); ++it ) {
262  if ( ( (*it)->resonance_id( 1 ) == resonance_id1 && (*it)->resonance_id( 2 ) == resonance_id2 )
263  && ( (*it)->resonance_id( 1 ) == resonance_id2 && (*it)->resonance_id( 2 ) == resonance_id1 ) ) {
264  intra_res_NOEs.push_back( *it );
265  }
266  }
267 }
268 
269 Real sum_IntraNOE( PeakAssignments const& list, id::NamedAtomID const& atom1, id::NamedAtomID const& atom2 ) {
270  Real intra_sumV( 0.0 );
271  for ( PeakAssignments::const_iterator it = list.begin(); it != list.end(); ++it ) {
272  if ( ( (*it)->atom( 1 ) == atom1 && (*it)->atom( 2 ) == atom2 )
273  && ( (*it)->atom( 1 ) == atom2 && (*it)->atom( 2 ) == atom1 ) ) {
274  intra_sumV+=(*it)->normalized_peak_volume();
275  }
276  }
277  return intra_sumV;
278 }
279 
280 
281 void PeakAssignmentResidueMap::assignments( core::Size res1, core::Size res2, PeakAssignments& collector ) const {
282  basic::ProfileThis doit( basic::NOESY_ASSIGN_NETWORK_FIND_RAW_ASSIGN );
283  if ( res1 <= 0 || res2 <= 0 ) return;
284  if ( residues_.size() < res1 ) {
285  return;
286  }
287  PeakAssignmentMap::const_iterator res2_entry( residues_[ res1 ].find( res2 ) );
288  if ( res2_entry == residues_[ res1 ].end() ) {
289  return;
290  }
291  copy( res2_entry->second.begin(), res2_entry->second.end(), back_inserter( collector ) );
292 
293 }
294 
295 void PeakAssignmentResidueMap::fill_covalent_gammas( Size alpha_resid, std::map< core::id::NamedAtomID, bool >& collector ) const {
296  basic::ProfileThis doit( basic::NOESY_ASSIGN_NETWORK_FILL_COV_GAMMA );
297  //collector.get_allocator().allocate( 50 ); //no aminoacid with more than 16 atoms...
298  for ( Size resid = (alpha_resid > 1 ? alpha_resid - 1 : alpha_resid);
299  resid <= ( alpha_resid < atoms_.size() ? alpha_resid + 1 : atoms_.size() ); ++resid ) {
300  // tr.Trace << "fill_covalent_gammas: probe residue: " << resid << std::endl;
301  for ( AtomList::const_iterator it = atoms_[ resid ].begin(); it != atoms_[ resid ].end(); ++it ) {
302  // tr.Trace << "fill_covalent_gammas: check atom: " << *it << std::endl;
303  //to get integration test back: take only resonance ides within -30+30 of alpha
304  // Size new_reso_id( resonances[ *it ].label() );
305  //if ( new_reso_id<= alpha-30 ) continue;
306  // if ( new_reso_id>= alpha+30 ) continue;
307  collector.insert( std::make_pair( *it, false ) );
308  }
309  }
310  //assume that residues are sequential in resonance list, as they usually are...
311  // core::Size const start( alpha >= ( 30 + resonances().start_key() ) ? alpha-30 : resonances().start_key() );
312  // core::Size const end( alpha + 30 < resonances().last_key() ? alpha+30 : resonances().last_key() );
313  // for ( Size ind = start; ind <= end; ind++ ) {
314  // try {
315  // Size const new_resid( resonances()[ ind ].resid() );
316  // if ( new_resid == alpha_resid || new_resid == alpha_resid - 1 || new_resid == alpha_resid + 1 ) {
317  // collector[ ind ] = false;
318  // }
319  // } catch ( EXCN_UnknownResonance& ) {
320 // continue;
321 // }
322 // }
323 }
324 
325 Real PeakAssignmentResidueMap::compute_Nk(
326  PeakAssignment const& alpha_beta,
327  id::NamedAtomID const& gamma_atom,
328  // Size gamma_ind, //is 1 or 2 relation to previous code: gamma_old = ag_or_bg.resonance_id( gamma_new );
329  bool connect_in_i,
330  bool connect_in_j,
331  bool sequential,
332  PeakAssignments const& close_to_i_assignments,
333  PeakAssignments const& close_to_j_assignments,
334  Real longrange_peak_volume
335 ) const {
336  basic::ProfileThis doit( basic::NOESY_ASSIGN_NETWORK_COMPUTE_NK );
337  PeakAssignmentParameters const& params( *PeakAssignmentParameters::get_instance() );
338  Real const vmax( params.vmax_ );
339  Real const vmin( params.vmin_ );
340 
341 // Size const alpha( alpha_beta.resonance_id( 1 ) );
342 // Size const beta( alpha_beta.resonance_id( 2 ) );
343  // Size const gamma( ag_or_bg.resonance_id( gamma_ind ) );
344  //find out if we have an initial assignment to gamma
345  ///WHAT IF I FIND MULTIPLE alpha - gamma assignments
346 
347  // PeakAssignments intra_residue_NOEs_ag;
348  // intra_residue_NOEs_ag.reserve( 1000 );
349  Real intra_sumV_ag( 0.0 );
350  if ( connect_in_i ) intra_sumV_ag = sum_IntraNOE( close_to_i_assignments, alpha_beta.atom( 1 ), gamma_atom ); //find all assignments with alpha and gamma (both directions)
351 // for ( PeakAssignments::const_iterator it = intra_residue_NOEs_ag.begin(); it != intra_residue_NOEs_ag.end(); ++it ) {
352 // intra_sumV_ag+=(*it)->normalized_peak_volume();
353 // }
354 
355  PeakAssignments intra_residue_NOEs_bg;
356  // intra_residue_NOEs_bg.reserve( 1000 );
357  Real intra_sumV_bg( 0.0 );
358  if ( connect_in_j ) intra_sumV_bg = sum_IntraNOE( close_to_j_assignments, alpha_beta.atom( 2 ), gamma_atom ); //find all assignments with alpha and gamma
359 // for ( PeakAssignments::const_iterator it = intra_residue_NOEs_bg.begin(); it != intra_residue_NOEs_bg.end(); ++it ) {
360 // intra_sumV_bg+=(*it)->normalized_peak_volume();
361 // }
362 
363  //( ag_or_bg.atom( gamma_ind ) );
364  bool const is_covalent_ag( covalent_compliance( alpha_beta.atom( 1 ), gamma_atom ) );
365  bool const is_covalent_bg( covalent_compliance( gamma_atom, alpha_beta.atom( 2 ) ) );
366  Real const Vcc_ag( is_covalent_ag ? vmax : ( ( connect_in_i || sequential ) ? vmin : 0 ) );
367  Real const Vcc_bg( is_covalent_bg ? vmax : ( ( connect_in_j || sequential ) ? vmin : 0 ) );
368  Real const vag( std::max( Vcc_ag, connect_in_i ? intra_sumV_ag : longrange_peak_volume ) );
369  Real const vbg( std::max( Vcc_bg, connect_in_j ? intra_sumV_bg : longrange_peak_volume ) );
370 // tr.Trace << alpha_beta.atom( 1 ) << "-" << gamma_atom << "-" << alpha_beta.atom( 2 )
371 // << ": " << Vcc_ag << " " << Vcc_bg << " " << vag << " " << vbg << " / (vmin: " << vmin << ") "
372 // << intra_sumV_ag << " " << intra_sumV_bg << " " << longrange_peak_volume << " ==> " << sqrt( (vag<vmin || vbg < vmin )? 0 : vag*vbg ) << std::endl;
373 
374  if ( vag < vmin || vbg < vmin ) return 0.0;//Heavyside function //verbatim would mean that in case of vag == vmin , 0.5*vmin is returned... but that seems stupid.
375  return sqrt( vag*vbg );
376 }
377 
378 
380  Real intra_sumV( 0.0 );
381  for ( PeakAssignments::const_iterator it = list.begin(); it != list.end(); ++it ) {
382  if ( (*it)->resonance_id( 1 ) == i && (*it)->resonance_id( 2 ) == j ) {
383  intra_sumV+=(*it)->normalized_peak_volume();
384  }
385  }
386  return intra_sumV;
387 }
388 
389 void PeakAssignmentResidueMap::network_analysis2( ResonanceList const& resonances ) {
390  tr.Info << "start network analysis (type2)..." << std::endl;
391  typedef std::pair< core::Size, core::Size > ResonancePair;
392  typedef std::map< ResonancePair, core::Real > AnchorMap;
393  // typedef std::map< ResonancePair, bool > LazyMap;
394  PeakAssignmentParameters const& params( *PeakAssignmentParameters::get_instance() );
395  AnchorMap anchor_weights; //Farray would also be fine, but we need to map resonance keys to 1...N instead of using keys from input file
396  ObjexxFCL::FArray2D_double residue_sum( atoms_.size(), atoms_.size(), 0.0 );
397  // for ( ResonanceList::const_iterator rit=resonances.begin(); rit!=resonance.end(); ++rit ) {
398  // for ( ResonanceList::const_iterator rit=resonances.begin(); rit!=resonance.end(); ++rit ) {
399  // anchor_weights
400  //}
401  for ( ResidueList::const_iterator it = residues_.begin(); it != residues_.end(); ++it ) {
402  for ( PeakAssignmentMap::const_iterator mit = it->begin(); mit != it->end(); ++mit ) {
403  //list of assignments between a residue i (given by it) and another residue (given by mit)
404  PeakAssignments const& assignments_ij( mit->second );
405 
406  //determine which residues we are talking about:
407  PeakAssignment const& first_assignment( **assignments_ij.begin() );
408  Size const resi( first_assignment.resid( 1 ) );
409  Size const resj( first_assignment.resid( 2 ) );
410 
411  //get the list of inverse assignments
412  PeakAssignments const& assignments_ji( _assignments( resj, resi ) );
413 
414  //compute anchor_weight \nu(i,j)
415  bool sequential( std::abs( (int) resi- (int) resj ) <= 1 );
416  for ( PeakAssignments::const_iterator ait = assignments_ij.begin(); ait != assignments_ij.end(); ++ait ) {
417  //ait - is now the alpha, beta assignment whose Nk we want to get --- referring to guntert paper.
418  // PeakAssignmentParameters const& params( *PeakAssignmentParameters::get_instance() );
419  core::Size const i( (*ait)->resonance_id( 1 ) );
420  core::Size const j( (*ait)->resonance_id( 2 ) );
421  bool covalent( false );
422  if ( sequential ) {
423  covalent = covalent_compliance( (*ait)->atom(1), (*ait)->atom(2) );
424  }
425  ResonancePair ij( i,j );
426  ResonancePair ji( j,i );
427  if ( anchor_weights.find(ij) == anchor_weights.end() ) {
428  core::Real sum_pv( sum_peak_volumes( assignments_ij, i, j ) );
429  sum_pv += sum_peak_volumes( assignments_ji, j, i );
430  core::Real cov_contrib = covalent ? params.vmax_ : ( sequential ? params.vmin_ : 0 );
431  core::Real n_ij = std::max( sum_pv, cov_contrib );
432  if ( n_ij < params.vmin_ ) {
433  n_ij = 0;
434  }
435  anchor_weights[ij]= n_ij;
436  anchor_weights[ji]= n_ij;
437  } //not in AnchorMap yet.
438  } //all assignments i,j between resi, resj
439  } //iterate over all residue resj
440  }//iterate over all residues resi
441 
442 
443  //now reap the benefits...
444  for ( ResidueList::const_iterator it = residues_.begin(); it != residues_.end(); ++it ) {
445  for ( PeakAssignmentMap::const_iterator mit = it->begin(); mit != it->end(); ++mit ) {
446  //list of assignments between a residue i (given by it) and another residue (given by mit)
447  PeakAssignments const& assignments_ij( mit->second );
448 
449  //determine which residues we are talking about:
450  PeakAssignment const& first_assignment( **assignments_ij.begin() );
451  Size const resi( first_assignment.resid( 1 ) );
452  Size const resj( first_assignment.resid( 2 ) );
453 
454  //are resi and resj sequential
455  bool sequential( std::abs( (int) resi- (int) resj ) <= 1 );
456 
457  //get all resonances K that could potentiall give us a triangle i, j, k
459  std::set< core::Size > neighbor_residues;
460  for ( Size i = ( resi > 1 ? resi -1 : resi ); i<= ( resi < atoms_.size() ? resi + 1 : resi ); ++i ) {
461  neighbor_residues.insert( i );
462  }
463  for ( Size i = ( resj > 1 ? resj -1 : resj ); i<= ( resj < atoms_.size() ? resj + 1 : resj ); ++i ) {
464  neighbor_residues.insert( i );
465  }
466  for ( std::set< core::Size >::const_iterator sit=neighbor_residues.begin(); sit!=neighbor_residues.end(); ++sit ) {
467  try {
468  ResonanceList::Resonances const& retrieved( resonances.resonances_at_residue( *sit ) );
469  copy( retrieved.begin(), retrieved.end(), back_inserter( resK ) );
470  } catch ( EXCN_UnknownResonance excn ) {
471  }
472  }
473 
474  core::Real sumNK_resij( 0.0 );
475  //now compute network anchoring for each assignment between residue-i and residue-j
476  for ( PeakAssignments::const_iterator ait = assignments_ij.begin(); ait != assignments_ij.end(); ++ait ) {
477  core::Size const i( (*ait)->resonance_id( 1 ) );
478  core::Size const j( (*ait)->resonance_id( 2 ) );
479 
480  core::Real sumNK( 0 );
481  for ( ResonanceList::Resonances::const_iterator itK = resK.begin(); itK != resK.end(); ++itK ) {
482  if ( !(*itK)->is_proton() ) continue;
483  if ( (*itK)->label() == i || (*itK)->label() == j ) continue;
484  core::Size const k( (*itK)->label() );
485  ResonancePair ik( i,k );
486  ResonancePair kj( k,j );
487  core::Real wik, wkj;
488 
489  wik=0.0;
490  AnchorMap::const_iterator nik( anchor_weights.find(ik) );
491  if ( nik == anchor_weights.end() ) { //not computed yet --- definitely no assignments for ik, just add covalent crap
492  bool sequential = std::abs( (int) resi - (int) (*itK)->resid() ) <= 1;
493  bool covalent( false );
494  if ( sequential ) {
495  covalent = covalent_compliance( (*ait)->atom(1), (*itK)->atom() );
496  }
497  wik = covalent ? params.vmax_ : ( sequential ? params.vmin_ : 0 );
498  anchor_weights[ik] = wik;
499  anchor_weights[ResonancePair(k,i)] = wik;
500  }
501  wik=std::max( wik, nik->second );
502 
503  wkj=0.0;
504  AnchorMap::const_iterator nkj( anchor_weights.find(kj) );
505  if ( nkj == anchor_weights.end() ) { //not computed yet --- definitely no assignments for kj, just add covalent crap
506  bool sequential = std::abs( (int) resj - (int) (*itK)->resid() ) <= 1;
507  bool covalent( false );
508  if ( sequential ) {
509  covalent = covalent_compliance( (*ait)->atom(2), (*itK)->atom() );
510  }
511  wkj = covalent ? params.vmax_ : ( sequential ? params.vmin_ : 0 );
512  anchor_weights[kj] = wkj;
513  anchor_weights[ResonancePair(j,k)] = wkj;
514  }
515  wkj = std::max( wkj, nkj->second );
516 
517  sumNK += sqrt( wik*wkj );
518 
519  }
520  (*ait)->set_network_anchoring( sumNK );
521  // tr.Debug << sumNK << " " << **ait << std::endl;
522  sumNK_resij+=sumNK;
523  } // for ait
524  residue_sum( resi, resj )+=sumNK_resij;
525  residue_sum( resj, resi )+=sumNK_resij;
526  } //resj
527  } //resi
528  for ( ResidueList::const_iterator it = residues_.begin(); it != residues_.end(); ++it ) {
529  for ( PeakAssignmentMap::const_iterator mit = it->begin(); mit != it->end(); ++mit ) {
530  PeakAssignments const& assignments_ij( mit->second );
531  //now cycle through all assignments between resi and resj
532  PeakAssignment const& first_assignment( **assignments_ij.begin() );
533  Size const resi( first_assignment.resid( 1 ) );
534  Size const resj( first_assignment.resid( 2 ) );
535  for ( PeakAssignments::const_iterator ait = assignments_ij.begin(); ait != assignments_ij.end(); ++ait ) {
536  (*ait)->set_network_anchoring_per_residue( residue_sum( resi, resj ) );
537  }
538  }
539  }
540 }
541 
542 void PeakAssignmentResidueMap::network_analysis( Size nr_assignments ) {
543  tr.Info << "network_analysis..." << std::endl;
544  PROF_START( NOESY_ASSIGN_NETWORK );
545 
546 
547  utility::vector1< core::Real > Nk_buf( nr_assignments );
548  utility::vector1< core::Real > reswise_Nk_buf( nr_assignments, 0.0 ); //this is longer than required...
549 
550  Size ct_buf( 1 );
551  Size ct_respair_buf( 0 );
552  // Real const vmax( 1.0 );
553  // Real const vmin( 0.1 );
554  //cycle through assigned pairs of residues
555  //compute Nk but store it temporarily in Nk_buf, since we don't want to change peak volumina mid-computation.
556  //store new Nks in assignments at end
557 
558  // this is more convenient because we need to retrieve i-i, i-j, and j-j information and can share this between
559  // all assignments that have the same pair i-j
560  for ( ResidueList::const_iterator it = residues_.begin(); it != residues_.end(); ++it ) {
561  for ( PeakAssignmentMap::const_iterator mit = it->begin(); mit != it->end(); ++mit ) {
562  PeakAssignments const& assignments_ij( mit->second );
563  runtime_assert( assignments_ij.size() > 0 ); // should not be in list if empty
564 
565  PeakAssignment const& first_assignment( **assignments_ij.begin() );
566  Size const resi( first_assignment.resid( 1 ) );
567  Size const resj( first_assignment.resid( 2 ) );
568 
569  // tr.Trace << "network ana of " << resi << " " << resj << std::endl;
570  ++ct_respair_buf;
571  // Real residue_wise_Nk( 0.0 );
572 
573  PeakAssignments assignments_around_ij;
574  assignments( resi-1, resj-1, assignments_around_ij );//why these ?
575  assignments( resi-1, resj, assignments_around_ij );
576  assignments( resi-1, resj+1, assignments_around_ij );//why these ?
577  assignments( resi , resj-1, assignments_around_ij );
578  assignments( resi , resj, assignments_around_ij );
579  assignments( resi , resj+1, assignments_around_ij );
580  assignments( resi+1, resj-1, assignments_around_ij );//why these ?
581  assignments( resi+1, resj, assignments_around_ij );
582  assignments( resi+1, resj+1, assignments_around_ij );//why these ?
583 
584  //makes results worse! rescoring tests on 4 targets (sr10, sgr145, rhodopsin, mbp) -- taken out on Nov 8th
585 // PeakAssignmentParameters const& params( *PeakAssignmentParameters::get_instance() );
586 // if ( params.network_include_reverse_dir_ ) {
587 // //20th Oct 2010: why not the opposite direction?
588 // assignments( resj-1, resi-1, assignments_around_ij );//why these ?
589 // assignments( resj-1, resi, assignments_around_ij );
590 // assignments( resj-1, resi+1, assignments_around_ij );//why these ?
591 // assignments( resj , resi-1, assignments_around_ij );
592 // assignments( resj , resi, assignments_around_ij );
593 // assignments( resj , resi+1, assignments_around_ij );
594 // assignments( resj+1, resi-1, assignments_around_ij );//why these ?
595 // assignments( resj+1, resi, assignments_around_ij );
596 // assignments( resj+1, resi+1, assignments_around_ij );//why these ?
597 
598 // }
599 
600  //get i-i and j-j assignments - use the method _X that returns BOGUS_ASSIGNMENTS and doesn't throw exception
601 // PeakAssignments const& intra_i_assignments( _assignments( resi, resi ) );
602 // PeakAssignments const& intra_j_assignments( _assignments( resj, resj ) );
603 
604  //we want to look for gamma atoms that help us to connect i -- > j
605  //these can come from same or neighbouring residue, hence we require assignments i -> i-1/i/i+1 or j-1/j/j+1 -> j
606  //to start in i or end in j.
607 
608  // std::cout << "START NEW RESIDUE PAIR " << resi << " " << resj << std::endl;
609 
610  /* for ( PeakAssignments::const_iterator yit = assignments_ij.begin(); yit != assignments_ij.end(); ++yit ) {
611  std::cout << **yit << std::endl;
612  }
613  std::cout << "--------------------------------------------------" << std::endl;
614  for ( PeakAssignments::const_iterator yit = assignments_around_ij.begin(); yit != assignments_around_ij.end(); ++yit ) {
615  std::cout << **yit << std::endl;
616  }
617  */
618  PeakAssignments close_to_i_assignments;
619  assignments( resi, resi-1, close_to_i_assignments );
620  assignments( resi, resi, close_to_i_assignments );
621  assignments( resi, resi+1, close_to_i_assignments );
622 
623  PeakAssignments close_to_j_assignments;
624  assignments( resj-1, resj, close_to_j_assignments );
625  assignments( resj, resj, close_to_j_assignments );
626  assignments( resj+1, resj, close_to_j_assignments );
627 
628  //now cycle through all assignments between resi and resj
629  for ( PeakAssignments::const_iterator ait = assignments_ij.begin(); ait != assignments_ij.end(); ++ait ) {
630  //ait - is now the alpha, beta assignment whose Nk we want to get --- referring to guntert paper.
631 
632  // PeakAssignmentParameters const& params( *PeakAssignmentParameters::get_instance() );
633 
634  bool is4D( (*ait)->crosspeak().is4D() );
635  if ( is4D ) {
636  Real sum_Nk = 1.0;
637  Nk_buf[ ct_buf++ ]=sum_Nk;
638  reswise_Nk_buf[ ct_respair_buf ] += sum_Nk;
639  continue;
640  }
641 
642  //Size const alpha( (*ait)->resonance_id( 1 ) );
643  //Size const beta( (*ait)->resonance_id( 2 ) );
644  Size const alpha_resid( (*ait)->resid( 1 ) );
645  Size const beta_resid( (*ait)->resid( 2 ) );
646  core::id::NamedAtomID const& alpha_atom( (*ait)->atom( 1 ) );
647  core::id::NamedAtomID const& beta_atom( (*ait)->atom( 2 ) );
648 // if ( tr.Trace.visible() ) {
649 // PeakAssignment const& assignment( **ait );
650 // Size const resi( assignment.resid( 1 ) );
651 // Size const resj( assignment.resid( 2 ) );
652 // tr.Trace << alpha << " " << resi << " " << beta << " " << resj << std::endl;
653 // tr.Trace << "human readable: " << resonances()[ alpha ].atom() << " -- " << resonances()[ beta ].atom() << std::endl;
654 // }
655 
656  core::Size const seq_dist( resi < resj ? resj - resi : resi - resj );
657  std::map< id::NamedAtomID, bool > covalent_gammas; //visited this gamma atom already ?
658  if ( seq_dist <= 2 ) {
659  fill_covalent_gammas( alpha_resid, covalent_gammas );
660  fill_covalent_gammas( beta_resid, covalent_gammas );
661  }
662  //make list of covalent structure gamma atoms
663 
664  Real sum_Nk( 0.0 );
665  ///cycle through all "gamma" atoms
666 
667  /// first count how often each peak is in the gamma list... multiple ambiguous assignments of a single peak should not just add up to provide a strong network
668  /// thus we count how often each peak appears and then normalize by that number.
669  std::map< std::string, core::Size > offset_map; //to provide a quick peak_id multiplicator.
670  std::map< core::Size, core::Size > peak_count_map;
671  core::Size next_offset( 100000000 ); //expect to have peak_id smaller than that value.
672  core::Size last_offset( next_offset );
673  { basic::ProfileThis doit( basic::NOESY_ASSIGN_NETWORK_PEAK_COUNT );
674  offset_map[ (*ait)->crosspeak().filename() ] = 0;
675  peak_count_map[ 0+(*ait)->crosspeak().peak_id() ] = 1;
676  for ( PeakAssignments::const_iterator yit = assignments_around_ij.begin(); yit != assignments_around_ij.end(); ++yit ) {
677  std::map< std::string, core::Size >::iterator file_it = offset_map.find( (*yit)->crosspeak().filename() );
678  core::Size offset;
679  if ( file_it != offset_map.end() ) {
680  offset = file_it->second;
681  } else { //new filename
682  offset_map[ (*yit)->crosspeak().filename() ] = last_offset;
683  offset = last_offset;
684  last_offset += next_offset;
685  }
686  peak_count_map[ offset+(*yit)->crosspeak().peak_id() ] += 1;
687  }
688  } //scope
689 
690  for ( PeakAssignments::const_iterator yit = assignments_around_ij.begin(); yit != assignments_around_ij.end(); ++yit ) {
691  //ignore assignments that are from the same peak... how can these possibly make the case stronger:
692  //offset of current crosspeak (*ait)->crosspeak() is 0 by construction
693  if ( 0+(*ait)->crosspeak().peak_id() == (offset_map[ (*yit)->crosspeak().filename() ]+(*yit)->crosspeak().peak_id()) ) {
694  // if ( tr.Trace.visible() ) { // tr.Trace << "ignore assignment of same peak: " << resonances()[ (*yit)->resonance_id( 1 ) ].atom() << " " << resonances()[ (*yit)->resonance_id( 2 ) ].atom() << std::endl;
695  // }
696  continue;
697  }
698  //the i-j assignment must be either gamma-alpha or gamma-beta, find out which
699  Size gamma_sel( 0 ); //which resonance id for atom gamma?
700  bool connect_in_i( false );
701  bool connect_in_j( false );
702  bool sequential( false );
703  Size my_res( 0 );
704 
705 
706  //// NOTE this comparison has to be via NamedAtomID ...
707  //// actaually we need somthing like a NMRAtomID to take care of QD1 ambiguities?
708  ////
709 
710  // if yit is gamma-beta in (i-j), gamma is residue i, ie., connect_in_i
711  id::NamedAtomID const& g_atom1( (*yit)->atom( 1 ) );
712  id::NamedAtomID const& g_atom2( (*yit)->atom( 2 ) );
713  if ( g_atom1 != alpha_atom && g_atom2 == beta_atom ) {
714  connect_in_i = true;
715  connect_in_j = false;
716  gamma_sel = 1;
717  my_res = resj;
718  }
719 
720  if ( g_atom2 != alpha_atom && g_atom1 == beta_atom ) {
721  connect_in_i = true;
722  connect_in_j = false;
723  gamma_sel = 2;
724  my_res = resj;
725  // // makes results worse : rescoring test on 4 targets --- removed Nov 8th.
726  // std::cout << "working on: " << **ait << std::endl;
727  // std::cout << "gamma: " << **yit << std::endl;
728  // std::cout << gamma_sel << " " << my_res << " " << connect_in_i << std::endl;
729  }
730 
731  // if yit is alpha-gamma in (i-j), gamma is residue j, ie., !connect_in_i
732  if ( g_atom1 == alpha_atom && g_atom2 != beta_atom ) {
733  connect_in_i = false;
734  connect_in_j = true;
735  gamma_sel = 2;
736  my_res = resi;
737  }
738 
739  if ( g_atom2 == alpha_atom && g_atom1 != beta_atom ) {
740  connect_in_i = false;
741  connect_in_j = true;
742  gamma_sel = 1;
743  my_res = resi;
744  // // makes results worse : rescoring test on 4 targets --- removed Nov 8th.
745  // std::cout << "working on: " << **ait << std::endl;
746  // std::cout << "gamma: " << **yit << std::endl;
747  // std::cout << gamma_sel << " " << my_res << " " << connect_in_i << std::endl;
748  }
749  if ( !gamma_sel ) continue; //this is a gamma, delta peak or another alpha, beta peak... no use
750  int const gamma_resid( (*yit)->resid( gamma_sel ) );
751  sequential = ( std::abs( (int) my_res - gamma_resid) <= 1 );
752 
753  // PeakAssignmentParameters const& params( *PeakAssignmentParameters::get_instance() );
754 // if ( params.network_allow_same_residue_connect_ ) {
755 
756 // //Extension Oct 2010
757 // // add also connections that go to same residue as alpha beta:
758 // if ( (*yit)->resonance_id( 1 )!=alpha && resonances()[ (*yit)->resonance_id( 2 ) ].resid() == resj ) {
759 // connect_in_i = true;
760 // connect_in_j = false;
761 // gamma = (*yit)->resonance_id( 1 );
762 // int const gamma_resid( (*yit)->resid( 1 ) );
763 // sequential = ( std::abs( (int) resj - gamma_resid) <= 1 );
764 // }
765 // if ( (*yit)->resonance_id( 2 )!=alpha && resonances()[ (*yit)->resonance_id( 1 ) ].resid() == resj ) {
766 // connect_in_i = true;
767 // connect_in_j = false;
768 // gamma = (*yit)->resonance_id( 2 );
769 // int const gamma_resid( (*yit)->resid( 2 ) );
770 // sequential = ( std::abs( (int) resj - gamma_resid) <= 1 );
771 // }
772 
773 
774 // if ( resonances()[ (*yit)->resonance_id( 1 ) ].resid() == resi && (*yit)->resonance_id( 2 )!=beta ) {
775 // connect_in_i = false;
776 // connect_in_j = true;
777 // gamma = (*yit)->resonance_id( 2 );
778 // int const gamma_resid( (*yit)->resid( 2 ) );
779 // sequential = ( std::abs( (int) resi - gamma_resid) <= 1 );
780 // }
781 // if ( resonances()[ (*yit)->resonance_id( 2 ) ].resid() == resi && (*yit)->resonance_id( 1 )!=beta ) {
782 // connect_in_i = false;
783 // connect_in_j = true;
784 // gamma = (*yit)->resonance_id( 1 );
785 // int const gamma_resid( (*yit)->resid( 1 ) );
786 // sequential = ( std::abs( (int) resi - gamma_resid) <= 1 );
787 // }
788 // } //same_residue_connect ---
789 
790 
791  // if ( tr.Trace.visible() && !gamma ) {
792 // tr.Trace << "no gamma found for " << resonances()[ (*yit)->resonance_id( 1 ) ].atom() << " " << resonances()[ (*yit)->resonance_id( 2 ) ].atom() << std::endl;
793  // }
794 
795  id::NamedAtomID const& gamma_atom( (*yit)->atom( gamma_sel ) );
796  if ( seq_dist <= 2 ) covalent_gammas[ gamma_atom ] = true; //this one has been visited
797 
798  Size ambiguity_factor( peak_count_map[ (*yit)->crosspeak().peak_id() + offset_map[ (*yit)->crosspeak().filename() ]] );
799 
800 // if ( tr.Trace.visible() ) {
801 // tr.Trace << "add: " << (*yit)->atom( 1 ) << " "
802 // << (*yit)->atom( 2 )
803 // << " from peak: " << (*yit)->crosspeak().peak_id() << " " << (*yit)->crosspeak().filename() << " ambiguity: " << ambiguity_factor
804 // << std::endl;
805 // }
806  sum_Nk += 1.0/ambiguity_factor* compute_Nk( **ait, gamma_atom, connect_in_i, connect_in_j,
807  sequential, close_to_i_assignments, close_to_j_assignments, (*yit)->normalized_peak_volume() );
808  // tr.Trace << gamma << " " << Vcc_ag << " " << vag << " " << vbg << " "
809  // << intra_sumV << " " << (*yit)->normalized_peak_volume() << std::endl;
810  }
811 // tr.Trace << "add covalent gammmas" << std::endl;
812  //iterate over missing covalent gammas
813  for ( std::map< core::id::NamedAtomID, bool >::const_iterator cgit = covalent_gammas.begin(); cgit != covalent_gammas.end(); cgit++ ) {
814  if ( cgit->second ) continue; // it has been visited
815  id::NamedAtomID const& gamma_atom( cgit->first );
816  int gamma_resid( gamma_atom.rsd() );
817  int res1( resi < resj ? resi : resj );
818  int res2( resi >= resj ? resi : resj );
819  bool connect_in_i( true );
820  bool connect_in_j( true );
821  // tr.Trace << "try gamma atom " << gamma_atom << std::endl;
822  //if i, i+2 gamma needs to be exactly between two residues to be effective
823  if ( seq_dist == 2 ) {
824  if ( !( gamma_resid-res1 == 1 || res2 - gamma_resid == 1 ) ) continue;
825  // connect_in_i = true;
826  // connect_in_j = true;
827  }
828 
829  if ( seq_dist == 1 ) { //gamma needs to be either in i or in j.
830  if ( gamma_resid != (int) resi && gamma_resid != (int) resj ) continue;
831  // if ( gamma_resid == resi ) connect_in_i = true;
832  // if ( gamma_resid == resj ) connect_in_j = true;
833  // if ( !( connect_in_i || connect_in_j ) ) continue;
834  }
835  sum_Nk += compute_Nk( **ait, gamma_atom, connect_in_i, connect_in_j, true, close_to_i_assignments, close_to_j_assignments, 0.0 /*no longrange NOE*/);
836  } //covalent gammas
837  // tr.Trace << "sum: " << sum_Nk << std::endl;
838  Nk_buf[ ct_buf++ ]=sum_Nk;
839  reswise_Nk_buf[ ct_respair_buf ] += sum_Nk;
840  }// all assignments between i-j
841 
842  } //all i
843  }// all assignments
844 
845  //now fill Nks into the PeakAssignments. use same sequence all i, all j (in i-j), all in i-j
846  ct_buf = 1;
847  ct_respair_buf = 1;
848  for ( ResidueList::const_iterator it = residues_.begin(); it != residues_.end(); ++it ) {
849  for ( PeakAssignmentMap::const_iterator mit = it->begin(); mit != it->end(); ++mit ) {
850  PeakAssignments const& assignments_ij( mit->second );
851 
852  //now cycle through all assignments between resi and resj
853  for ( PeakAssignments::const_iterator ait = assignments_ij.begin(); ait != assignments_ij.end(); ++ait ) {
854  (*ait)->set_network_anchoring( Nk_buf[ ct_buf++ ] );
855  (*ait)->set_network_anchoring_per_residue( reswise_Nk_buf[ ct_respair_buf ] );
856  }
857  ++ct_respair_buf;
858  }
859  }
860 
861  PROF_STOP( NOESY_ASSIGN_NETWORK );
862 
863 }
864 
865 
866 } //noesy_assign
867 } //protocols