Rosetta 3.5
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
ResidueNeighborList.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/ResidueNeighborList.hh
11 /// @brief A container class for use by the Etable and HackElec classes for storing
12 /// lists of atom neighbors
13 /// @author Andrew Leaver-Fay
14 
15 // Unit headers
17 
18 // Package headers
20 
21 // Project headers
24 
25 /// Utility headers
26 #include <utility/vector0.hh>
27 
28 #include <utility/vector1.hh>
29 
30 
31 /// #define APL_TEMP_DEBUG
32 
33 namespace core {
34 namespace scoring {
35 
36 /*
37 const Real ResiduePairNeighborList::narrow_reach = { 0.55 };
38 const Real ResiduePairNeighborList::wide_reach = { 2.0 };
39 
40 Real const nr2 = 2 * ResiduePairNeighborList::narrow_reach;
41 Real const wr2 = 2 * ResiduePairNeighborList::wide_reach;
42 
43 void
44 initialize_cut2(
45  Real heavy_heavy_dist_cutoff,
46  Real heavy_hydrogen_dist_cutoff,
47  Real hydrogen_hydrogen_dist_cutoff,
48  Real * ncut2,
49  Real * wcut2
50 )
51 {
52 
53  Real ncut[ 3 ] = { heavy_heavy_dist_cutoff + nr2, heavy_hydrogen_dist_cutoff + nr2, hydrogen_hydrogen_dist_cutoff + nr2 };
54  Real wcut[ 3 ] = { heavy_heavy_dist_cutoff + wr2, heavy_hydrogen_dist_cutoff + wr2, hydrogen_hydrogen_dist_cutoff + wr2 };
55 
56  ncut2[ 0 ] = ncut[ 0 ] * ncut[ 0 ];
57  ncut2[ 1 ] = ncut[ 1 ] * ncut[ 1 ];
58  ncut2[ 2 ] = ncut[ 2 ] * ncut[ 2 ];
59 
60  wcut2[ 0 ] = wcut[ 0 ] * wcut[ 0 ];
61  wcut2[ 1 ] = wcut[ 1 ] * wcut[ 1 ];
62  wcut2[ 2 ] = wcut[ 2 ] * wcut[ 2 ];
63 
64 }
65 
66 
67 #ifdef APL_TEMP_DEBUG
68 Size profile_natoms = 0;
69 Size profile_nwide_update = 0;
70 Size profile_nnarrow_update = 0;
71 Size profile_nwide_update_total = 0;
72 Size profile_nnarrow_update_total = 0;
73 bool profile_nodes_processed = false;
74 Size profile_update_calls = 0;
75 Size n_narrow_dist_evals = 0;
76 Size n_wide_dist_evals = 0;
77 Size n_update_dist_evals = 0;
78 Size n_update_dist_evals_total = 0;
79 Size n_empty_edges = 0;
80 Size n_zero_neighb_atoms = 0;
81 Size n_some_neighb_atoms = 0;
82 #endif
83 
84 
85 ResidueNblistData::ResidueNblistData() : nnarrow_ood_( 0 ), nwide_ood_( 0 ) {}
86 ResidueNblistData::~ResidueNblistData()
87 {
88 #ifdef APL_TEMP_DEBUG
89  /// APL DEBUG TEMP
90  if ( profile_update_calls != 0 || n_zero_neighb_atoms != 0 ) {
91  std::cout << "#updates = " << profile_update_calls << " #narrow "
92  << profile_nnarrow_update_total << " #wide " << profile_nwide_update_total << " %narrow "
93  << ( (double) profile_nnarrow_update_total ) / ( profile_natoms * profile_update_calls )
94  << " %wide " << ( (double) profile_nwide_update_total ) / (profile_natoms * profile_update_calls )
95  << " dis/update: " << (double) n_update_dist_evals_total / (profile_natoms * profile_update_calls)
96  << " dis/wideood: " << (double) n_wide_dist_evals / (profile_nwide_update_total)
97  << " dis/narrowood: " << (double) n_narrow_dist_evals / (profile_nnarrow_update_total) << std::endl;
98  std::cout << "#zero neighb atoms: " << n_zero_neighb_atoms << " #some neighb atoms: " << n_some_neighb_atoms << std::endl;
99  profile_natoms = 0;
100  profile_nwide_update = 0;
101  profile_nnarrow_update = 0;
102  profile_nwide_update_total = 0;
103  profile_nnarrow_update_total = 0;
104  profile_nodes_processed = false;
105  profile_update_calls = 0;
106  n_narrow_dist_evals = 0;
107  n_wide_dist_evals = 0;
108  n_update_dist_evals = 0;
109  n_update_dist_evals_total = 0;
110  n_zero_neighb_atoms = 0;
111  n_some_neighb_atoms = 0;
112  }
113 #endif
114 }
115 
116 ResidueNblistData::CacheableDataOP ResidueNblistData::clone() const
117 {
118  return new ResidueNblistData( *this );
119 }
120 
121 void
122 ResidueNblistData::setup_for_intrares_nblist(
123  CountPairFunctionCOP cpfxn,
124  Real heavy_heavy_dist_cutoff,
125  Real heavy_hydrogen_dist_cutoff,
126  Real hydrogen_hydrogen_dist_cutoff
127 )
128 {
129  cpfxn_ = cpfxn;
130  initialize_cut2( heavy_heavy_dist_cutoff, heavy_hydrogen_dist_cutoff, hydrogen_hydrogen_dist_cutoff, ncut2_, wcut2_ );
131 }
132 
133 void ResidueNblistData::initialize( conformation::Residue const & res )
134 {
135 
136  Size const natoms( res.natoms() );
137  is_H_.resize( natoms );
138  ood_status_.resize( natoms );
139  narrow_ood_list_.resize( natoms );
140  wide_ood_list_.resize( natoms );
141  narrow_coord_.resize( natoms );
142  wide_coord_.resize( natoms );
143  at_neighbors_.resize( natoms );
144 
145 #ifdef APL_TEMP_DEBUG
146  /// APL DEBUG TEMP
147  profile_natoms += natoms;
148 #endif
149 
150  Real maxd2_to_nbrat;
151  Vector nbrxyz = res.xyz( res.nbr_atom() );
152  for ( Size ii = 1; ii <= is_H_.size(); ++ii ) {
153  Real d2_to_nbrat = res.xyz( ii ).distance_squared( nbrxyz );
154  if ( ii == 1 || d2_to_nbrat > maxd2_to_nbrat ) {
155  maxd2_to_nbrat = d2_to_nbrat;
156  }
157  is_H_[ ii ] = res.atom_is_hydrogen( ii ) ? 1 : 0;
158  ood_status_[ ii ] = uptodate;
159  wide_coord_[ ii ] = narrow_coord_[ ii ] = res.xyz( ii );
160  }
161 
162  if ( ! cpfxn_ ) return;
163 
164  if ( narrow_.size() < natoms ) {
165  narrow_.resize( natoms );
166  wide_.resize( natoms );
167  }
168  for ( Size ii = 1; ii <= natoms; ++ii ) {
169  narrow_[ ii ].resize( natoms );
170  wide_[ ii ].resize( natoms );
171  }
172 
173  for ( Size ii = 1; ii <= natoms; ++ii ) {
174  for ( Size jj = ii + 1; jj <= natoms; ++jj ) {
175  Real weight( 1.0 );
176  Size path_dist( 0 );
177  if ( cpfxn_->count( ii, jj, weight, path_dist ) ) {
178  Real d2 = res.xyz( ii ).distance_squared( res.xyz( jj ) );
179  if ( d2 < wcut2_[ is_H_[ ii ] + is_H_[ jj ] ] ) {
180 
181  wide_[ ii ][ jj ].data() = AtomNeighbor( res.seqpos(), jj, path_dist, weight );
182  wide_[ jj ][ ii ].data() = AtomNeighbor( res.seqpos(), ii, path_dist, weight );
183  wide_[ ii ].move_to_back( jj );
184  wide_[ jj ].move_to_back( ii );
185  if ( d2 < ncut2_[ is_H_[ ii ] + is_H_[ jj ] ] ) {
186  narrow_[ ii ][ jj ].data() = wide_[ ii ][ jj ].data();
187  narrow_[ jj ][ ii ].data() = wide_[ jj ][ ii ].data();
188  narrow_[ ii ].move_to_back( jj );
189  narrow_[ jj ].move_to_back( ii );
190  at_neighbors_[ ii ].push_back( wide_[ ii ][ jj ].data() );
191  //at_neighbors_[ jj ].push_back( wide_[ jj ][ ii ].data() );
192 
193  }
194  }
195  }
196  }
197  }
198 }
199 
200 
201 void ResidueNblistData::update( conformation::Residue const & res )
202 {
203  //return; /// TEMP!!!! Short circuit the whole thing
204 #ifdef APL_TEMP_DEBUG
205  /// APL TEMP
206  if ( ! profile_nodes_processed ) {
207  std::cout << "Last update: " << n_update_dist_evals << " distance evaluations" << std::endl;
208  n_update_dist_evals = 0;
209  ++profile_update_calls;
210  profile_nodes_processed = true;
211  }
212 #endif
213  Real wide_movement_cutoff( ResiduePairNeighborList::wide_reach - ResiduePairNeighborList::narrow_reach );
214  Real wide_movement_cutoff2( wide_movement_cutoff * wide_movement_cutoff );
215 
216  nnarrow_ood_ = 0;
217  nwide_ood_ = 0;
218  narrow_ood_list_.clear();
219  wide_ood_list_.clear();
220 
221  for ( Size ii = 1; ii <= res.natoms(); ++ii ) {
222  Real d2narrow = narrow_coord_[ ii ].distance_squared( res.xyz( ii ) );
223  if ( d2narrow > ResiduePairNeighborList::narrow_reach ) {
224  Real d2wide = wide_coord_[ ii ].distance_squared( res.xyz( ii ) );
225  if ( d2wide > wide_movement_cutoff2 ) {
226  wide_ood_list_.move_to_back( ii );
227  ++nwide_ood_;
228 
229 #ifdef APL_TEMP_DEBUG
230  ++profile_nwide_update;
231  ++profile_nwide_update_total;
232 #endif
233 
234  ood_status_[ ii ] = wide_ood;
235  wide_coord_[ ii ] = res.xyz( ii );
236  } else {
237 #ifdef APL_TEMP_DEBUG
238  /// APL TEMP
239  ++profile_nnarrow_update;
240  ++profile_nnarrow_update_total;
241 #endif
242  ++nnarrow_ood_;
243  narrow_ood_list_.move_to_back( ii );
244  ood_status_[ ii ] = narrow_ood;
245  }
246  narrow_coord_[ ii ] = res.xyz( ii );
247  } else {
248  ood_status_[ ii ] = uptodate;
249  }
250  }
251 
252  if ( ! cpfxn_ ) return;
253 
254  for ( Size ii = 1; ii <= res.natoms(); ++ii ) {
255  if ( ood_status_[ ii ] == uptodate ) continue;
256  if ( ood_status_[ ii ] == narrow_ood ) {
257  for ( Size jj = narrow_[ ii ].head(), jjend = narrow_[ ii ].end(); jj != jjend; jj = narrow_[ ii ][ jj ].next() ) {
258  Size jjatno = narrow_[ ii ][ jj ].data().atomno();
259  if ( narrow_[ jjatno ][ ii ].in_list() ) { narrow_[ jjatno ].remove( ii ); }
260  }
261  narrow_[ ii ].clear();
262  } else {
263  assert( ood_status_[ ii ] == wide_ood );
264  for ( Size jj = wide_[ ii ].head(), jjend = wide_[ ii ].end(); jj != jjend; jj = wide_[ ii ][ jj ].next() ) {
265  Size jjatno = wide_[ ii ][ jj ].data().atomno();
266  if ( wide_[ jjatno ][ ii ].in_list() ) { wide_[ jjatno ].remove( ii ); }
267  }
268  wide_[ ii ].clear();
269  for ( Size jj = narrow_[ ii ].head(), jjend = narrow_[ ii ].end(); jj != jjend; jj = narrow_[ ii ][ jj ].next() ) {
270  Size jjatno = narrow_[ ii ][ jj ].data().atomno();
271  if ( narrow_[ jjatno ][ ii ].in_list() ) { narrow_[ jjatno ].remove( ii ); }
272  }
273  narrow_[ ii ].clear();
274  }
275  }
276  for ( Size ii = 1; ii <= res.natoms(); ++ii ) {
277  if ( ood_status_[ ii ] == uptodate ) continue;
278  int ii_isH = is_H_[ ii ] ? 1 : 0;
279  if ( ood_status_[ ii ] == narrow_ood ) {
280  AtomNeighbors const & iiwide( wide_[ ii ] );
281  for ( Size jj = iiwide.head(), jjend = iiwide.end(); jj != jjend; jj = iiwide[ jj ].next() ) {
282  Size jjatno = iiwide[ jj ].data().atomno();
283  if ( ii > jjatno && ood_status_[ jjatno ] != uptodate ) continue; // we've already visited this atpair
284  if ( ood_status_[ jjatno ] == wide_ood ) continue; // wait until the wide list is up to date
285  assert( ! narrow_[ ii ][ jjatno ].in_list() );
286  assert( ! narrow_[ jjatno ][ ii ].in_list() );
287  assert( wide_[ jjatno ][ ii ].in_list() );
288  int jj_isH = is_H_[ jjatno ];
289  Real d2 = narrow_coord_[ ii ].distance_squared( narrow_coord_[ jj ] );
290  if ( d2 < ncut2_[ ii_isH + jj_isH ] ) {
291  narrow_[ ii ][ jjatno ].data() = iiwide[ jjatno ].data();
292  narrow_[ ii ].move_to_back( jjatno );
293  narrow_[ jjatno ][ ii ].data() = wide_[ jjatno ][ ii ].data();
294  narrow_[ jjatno ].move_to_back( ii );
295  }
296  }
297  } else {
298  int ii_isH = is_H_[ ii ];
299  for ( Size jj = 1; jj <= res.natoms(); ++jj ) {
300  if ( ii > jj && ood_status_[ jj ] == wide_ood ) continue; // already visited
301  assert( ! narrow_[ ii ][ jj ].in_list() );
302  assert( ! narrow_[ jj ][ ii ].in_list() );
303  assert( ! wide_[ ii ][ jj ].in_list() );
304  assert( ! wide_[ jj ][ ii ].in_list() );
305  Real weight( 1.0 ); Size path_dist( 0 );
306  if ( cpfxn_->count( ii, jj, weight, path_dist ) ) {
307  Real d2w = wide_coord_[ ii ].distance_squared( wide_coord_[ jj ] );
308  int jj_isH = is_H_[ jj ];
309  if ( d2w < wcut2_[ ii_isH + jj_isH ] ) {
310  wide_[ ii ][ jj ].data() = AtomNeighbor( res.seqpos(), jj, path_dist, weight );
311  wide_[ jj ][ ii ].data() = AtomNeighbor( res.seqpos(), ii, path_dist, weight );
312  wide_[ ii ].move_to_back( jj );
313  wide_[ jj ].move_to_back( ii );
314  Real d2n = narrow_coord_[ ii ].distance_squared( narrow_coord_[ jj ] );
315  if ( d2n < ncut2_[ ii_isH + jj_isH ] ) {
316  narrow_[ ii ][ jj ].data() = wide_[ ii ][ jj ].data();
317  narrow_[ jj ][ ii ].data() = wide_[ jj ][ ii ].data();
318  narrow_[ ii ].move_to_back( jj );
319  narrow_[ jj ].move_to_back( ii );
320  }
321  }
322  }
323  }
324  }
325  }
326 }
327 
328 //////////////////////////////////////////////////////
329 
330 ResiduePairNeighborList::ResiduePairNeighborList() {}
331 ResiduePairNeighborList::~ResiduePairNeighborList() {}
332 
333 ResiduePairNeighborList::CacheableDataOP
334 ResiduePairNeighborList::clone() const {
335  return new ResiduePairNeighborList( *this );
336 }
337 
338 void
339 ResiduePairNeighborList::initialize_from_residues(
340  Real heavy_heavy_dist_cutoff,
341  Real heavy_hydrogen_dist_cutoff,
342  Real hydrogen_hydrogen_dist_cutoff,
343  conformation::Residue const & r1,
344  conformation::Residue const & r2,
345  ResidueNblistData const & r1dat,
346  ResidueNblistData const & r2dat,
347  etable::count_pair::CountPairFunctionCOP cpfxn
348 )
349 {
350  cpfxn_ = cpfxn; // save this for use in update();
351  initialize_cut2( heavy_heavy_dist_cutoff, heavy_hydrogen_dist_cutoff, hydrogen_hydrogen_dist_cutoff, ncut2_, wcut2_ );
352 
353  r1_at_neighbors_.resize( r1.natoms() );
354  for ( Size ii = 1; ii <= r1.natoms(); ++ii ) {
355  r1_at_neighbors_[ ii ].reserve( r2.natoms() );
356  }
357  r2_at_neighbors_.resize( r2.natoms() );
358  r1_w_non_empty_narrow_.resize( r1.natoms() );
359 
360  for ( Size ii = 0; ii < 2; ++ii ) {
361  Size ii_natoms = ii == 0 ? r1.natoms() : r2.natoms();
362  Size other_natoms = ii == 1 ? r1.natoms() : r2.natoms();
363  if ( narrow(ii).size() < ii_natoms ) {
364  /// only grow the arrays
365  narrow(ii).resize( ii_natoms );
366  wide( ii ).resize( ii_natoms );
367  for ( Size jj = 1; jj <= ii_natoms; ++jj ) {
368  if ( narrow(ii)[ jj ].size() < other_natoms ) {
369  narrow(ii)[ jj ].resize( other_natoms );
370  wide(ii)[ jj ].resize( other_natoms );
371  } else {
372  narrow(ii)[ jj ].clear();
373  wide(ii)[ jj ].clear();
374  }
375  }
376  } else {
377  for ( Size jj = 1; jj <= ii_natoms; ++jj ) {
378  if ( narrow(ii)[ jj ].size() < other_natoms ) {
379  narrow(ii)[jj].resize( other_natoms );
380  wide(ii)[ jj].resize( other_natoms );
381  } else {
382  narrow(ii)[jj].clear();
383  wide(ii)[ jj].clear();
384  }
385  }
386  }
387  }
388 
389  for ( Size ii = 1; ii <= r1.natoms(); ++ii ) {
390  int ii_isH = r1dat.is_H( ii );
391  for ( Size jj = 1; jj <= r2.natoms(); ++jj ) {
392  int jj_isH = r2dat.is_H( jj );
393  Real weight( 1.0 );
394  Size pathdist( 0 );
395  if ( cpfxn_->count( ii, jj, weight, pathdist ) ) {
396  /// Set the atom-neighbor data even if these atoms never get scored together;
397  /// this saves us numerous copy operations later
398  wide(0)[ ii ][ jj ].data() = AtomNeighbor( r2.seqpos(), jj, pathdist, weight );
399  wide(1)[ jj ][ ii ].data() = AtomNeighbor( r1.seqpos(), ii, pathdist, weight );
400  narrow(0)[ ii ][ jj ].data() = wide(0)[ ii ][ jj ].data();
401  narrow(1)[ jj ][ ii ].data() = wide(1)[ jj ][ ii ].data();
402 
403  Real d2 = r1.xyz( ii ).distance_squared( r2.xyz( jj ) );
404  if ( d2 < wcut2_[ ii_isH + jj_isH ] ) {
405  wide(0)[ ii ].move_to_back( jj );
406  wide(1)[ jj ].move_to_back( ii );
407  if ( d2 < ncut2_[ ii_isH + jj_isH ] ) {
408  narrow(0)[ ii ].move_to_back( jj );
409  narrow(1)[ jj ].move_to_back( ii );
410  r1_at_neighbors_[ ii ].push_back( wide(0)[ ii ][ jj ].data() );
411  r2_at_neighbors_[ jj ].push_back( wide(1)[ jj ][ ii ].data() );
412  }
413  }
414  }
415  }
416  }
417  for ( Size ii = 1; ii <= r1.natoms(); ++ii ) {
418  if ( narrow(0)[ii].head() != 0 ) {
419  r1_w_non_empty_narrow_.move_to_back( ii );
420  }
421  }
422 #ifdef APL_TEMP_DEBUG
423  for ( Size ii = 1; ii <= r1.natoms(); ++ii ) {
424  if ( narrow(0)[ii].head() == 0 ) {
425  ++n_zero_neighb_atoms;
426  } else {
427  ++n_some_neighb_atoms;
428  }
429  }
430 #endif
431 
432  //assert( accurate(
433  // heavy_heavy_dist_cutoff,
434  // heavy_hydrogen_dist_cutoff,
435  // hydrogen_hydrogen_dist_cutoff,
436  // r1, r2, r1dat, r2dat ) );
437 }
438 
439 void
440 ResiduePairNeighborList::update(
441  Real heavy_heavy_dist_cutoff,
442  Real heavy_hydrogen_dist_cutoff,
443  Real hydrogen_hydrogen_dist_cutoff,
444  conformation::Residue const & r1,
445  conformation::Residue const & r2,
446  ResidueNblistData const & r1dat,
447  ResidueNblistData const & r2dat
448 )
449 {
450  //return; // TEMP!!! short circuit the whole thing
451 #ifdef APL_TEMP_DEBUG
452  //std::cout << "update for pair " << r1.seqpos() << " " << r2.seqpos() << std::endl;
453  if ( profile_nodes_processed ) {
454  profile_nodes_processed = false;
455  std::cout << "Previous update: #atoms " << profile_natoms << " narrow " << profile_nnarrow_update << " wide " << profile_nwide_update << std::endl;
456  profile_nwide_update = 0;
457  profile_nnarrow_update = 0;
458  }
459 #endif
460 
461  if ( r1dat.nnarrow_ood() == 0 && r1dat.nwide_ood() == 0 && r2dat.nnarrow_ood() == 0 && r2dat.nwide_ood() == 0 ) return;
462 
463  /// 1. Remove all atom-neighbors in the narrow list for narrow_ood atoms
464  /// and all atom-neighbors from both the narrow and wide lists for wide_ood atoms
465 
466  /// 2. Add in atom neighbors for narrow_ood and wide_ood atoms
467 
468  /// 1a clear the neighbors for res1
469  //for ( Size ii = 1; ii <= r1.natoms(); ++ii ) {
470  for ( Size ii = r1dat.narrow_ood_list().head(); ii != 0; ii = r1dat.narrow_ood_list()[ ii ].next() ) {
471  //if ( r1dat.atom_status(ii) == uptodate ) continue;
472  assert( r1dat.atom_status(ii) == narrow_ood );
473  AtomNeighbors & iinarrow( narrow(0)[ ii ] );
474  for ( Size jj = iinarrow.head(), jjend = 0;
475  jj != jjend; jj = iinarrow[ jj ].next() ) {
476  if ( r2dat.atom_status( jj ) == uptodate ) {
477  narrow(1)[ jj ].remove( ii );
478  }
479  }
480  iinarrow.clear(); // O(k)
481  }
482  for ( Size ii = r1dat.wide_ood_list().head(); ii != 0; ii = r1dat.wide_ood_list()[ ii ].next() ) {
483  assert( r1dat.atom_status(ii) == wide_ood );
484  AtomNeighbors & iiwide( wide(0)[ ii ] );
485  for ( Size jj = iiwide.head(), jjend = 0;
486  jj != jjend; jj = iiwide[ jj ].next() ) {
487  if ( r2dat.atom_status( jj ) < wide_ood ) {
488  wide(1)[ jj ].remove( ii );
489  }
490  if ( r2dat.atom_status( jj ) == uptodate && narrow(1)[ jj ][ ii ].in_list() ) {
491  narrow(1)[ jj ].remove( ii );
492  }
493  }
494  iiwide.clear(); // O(k)
495  narrow(0)[ii].clear(); // O(k)
496  }
497 
498  /// 1b Clear the out of date lists for the res2
499  //for ( Size ii = 1; ii <= r2.natoms(); ++ii ) {
500  for ( Size ii = r2dat.narrow_ood_list().head(); ii != 0; ii = r2dat.narrow_ood_list()[ ii ].next() ) {
501  //if ( r2dat.atom_status(ii) == uptodate ) continue;
502  assert( r2dat.atom_status(ii) == narrow_ood );
503  AtomNeighbors & iinarrow( narrow(1)[ ii ] );
504  for ( Size jj = iinarrow.head(), jjend = 0;
505  jj != jjend; jj = iinarrow[ jj ].next() ) {
506  if ( r1dat.atom_status( jj ) == uptodate ) {
507  narrow(0)[ jj ].remove( ii );
508  }
509  }
510  iinarrow.clear(); // O(k)
511  }
512  for ( Size ii = r2dat.wide_ood_list().head(); ii != 0; ii = r2dat.wide_ood_list()[ ii ].next() ) {
513  assert( r2dat.atom_status(ii) == wide_ood );
514  AtomNeighbors & iiwide( wide(1)[ ii ] );
515  for ( Size jj = iiwide.head(), jjend = 0;
516  jj != jjend; jj = iiwide[ jj ].next() ) {
517  if ( r1dat.atom_status( jj ) < wide_ood ) {
518  wide(0)[ jj ].remove( ii );
519  }
520  if ( r1dat.atom_status( jj ) == uptodate && narrow(0)[ jj ][ ii ].in_list() ) {
521  narrow(0)[ jj ].remove( ii );
522  }
523  }
524  iiwide.clear(); // O(k)
525  narrow(1)[ii].clear(); // O(k)
526  }
527 
528  // 2a: r1 neighbor list updates
529  for ( Size ii = r1dat.narrow_ood_list().head(); ii != 0; ii = r1dat.narrow_ood_list()[ ii ].next() ) {
530  //if ( r1dat.atom_status(ii) == uptodate ) continue;
531  int ii_isH = r1dat.is_H( ii );
532  assert( r1dat.atom_status(ii) == narrow_ood );
533  AtomNeighbors const & iiwide( wide(0)[ ii ] );
534  for ( Size jj = iiwide.head(), jjend = 0;
535  jj != jjend; jj = iiwide[ jj ].next() ) {
536  int jj_isH = r2dat.is_H( jj );
537  Real d2 = r1dat.narrow_coord(ii).distance_squared( r2dat.narrow_coord(jj) );
538 
539 #ifdef APL_TEMP_DEBUG
540  /// APL TEMP
541  ++n_narrow_dist_evals;
542  ++n_update_dist_evals;
543  ++n_update_dist_evals_total;
544 #endif
545 
546  if ( d2 < ncut2_[ ii_isH + jj_isH ] ) {
547  assert( ! narrow(0)[ ii ][ jj ].in_list() );
548  assert( ! narrow(1)[ jj ][ ii ].in_list() );
549  //narrow(0)[ ii ][ jjatno ].data() = iiwide[ jjatno ].data();
550  narrow(0)[ ii ].move_to_back( jj );
551  //narrow(1)[ jjatno ][ ii ].data() = wide(1)[ jjatno ][ ii ].data();
552  narrow(1)[ jj ].move_to_back( ii );
553  }
554  }
555  }
556  for ( Size ii = r1dat.wide_ood_list().head(); ii != 0; ii = r1dat.wide_ood_list()[ ii ].next() ) {
557  //if ( r1dat.atom_status(ii) == uptodate ) continue;
558  int ii_isH = r1dat.is_H( ii );
559  assert( r1dat.atom_status(ii) == wide_ood );
560  for ( Size jj = 1; jj <= r2.natoms(); ++jj ) {
561  int jj_isH = r2dat.is_H( jj );
562  Real weight( 1.0 );
563  Size path_dist( 0 );
564  if ( cpfxn_->count( ii, jj, weight, path_dist ) ) {
565 #ifdef APL_TEMP_DEBUG
566  /// APL TEMP
567  ++n_wide_dist_evals;
568  ++n_update_dist_evals;
569  ++n_update_dist_evals_total;
570 #endif
571  Real d2w = r1dat.wide_coord( ii ).distance_squared( r2dat.wide_coord( jj ) );
572  if ( d2w < wcut2_[ ii_isH + jj_isH ] ) {
573  assert( ! wide(0)[ ii ][ jj ].in_list() ); // should have already been removed
574  assert( ! wide(1)[ jj ][ ii ].in_list() ); // should have already been removed
575  //wide(0)[ ii ][ jj ].data() = AtomNeighbor( r2.seqpos(), jj, path_dist, weight );
576  //wide(1)[ jj ][ ii ].data() = AtomNeighbor( r1.seqpos(), ii, path_dist, weight );
577  wide(0)[ ii ].move_to_back( jj );
578  wide(1)[ jj ].move_to_back( ii );
579  Real d2n = r1dat.narrow_coord( ii ).distance_squared( r2dat.narrow_coord( jj ) );
580 #ifdef APL_TEMP_DEBUG
581  /// APL TEMP
582  ++n_wide_dist_evals;
583  ++n_update_dist_evals;
584  ++n_update_dist_evals_total;
585 #endif
586 
587  if ( d2n < ncut2_[ ii_isH + jj_isH ] ) {
588  assert( ! narrow(0)[ ii ][ jj ].in_list() ); // should have already been removed
589  assert( ! narrow(1)[ jj ][ ii ].in_list() ); // should have already been removed
590  //narrow(0)[ ii ][ jj ].data() = wide(0)[ ii ][ jj ].data();
591  //narrow(1)[ jj ][ ii ].data() = wide(1)[ jj ][ ii ].data();
592  narrow(0)[ ii ].move_to_back( jj );
593  narrow(1)[ jj ].move_to_back( ii );
594  }
595  }
596  }
597  }
598  }
599 
600  // 2b res2 neighborlist updates -- some neighbors have already been detected from part 2a above
601  // (i.e. when an neighbor from res1 had status wide_ood)
602  for ( Size ii = r2dat.narrow_ood_list().head(); ii != 0; ii = r2dat.narrow_ood_list()[ ii ].next() ) {
603  int ii_isH = r2dat.is_H( ii );
604  assert ( r2dat.atom_status( ii ) == narrow_ood );
605  AtomNeighbors const & iiwide( wide(1)[ ii ] );
606  for ( Size jj = iiwide.head(), jjend = 0;
607  jj != jjend; jj = iiwide[ jj ].next() ) {
608  if ( r1dat.atom_status( jj ) != uptodate ) continue;
609  int jj_isH = r1dat.is_H( jj );
610  Real d2 = r2dat.narrow_coord(ii).distance_squared( r1dat.narrow_coord(jj) );
611  /// APL TEMP
612 #ifdef APL_TEMP_DEBUG
613  ++n_narrow_dist_evals;
614  ++n_update_dist_evals;
615  ++n_update_dist_evals_total;
616 #endif
617  if ( d2 < ncut2_[ ii_isH + jj_isH ] ) {
618  assert( ! narrow(1)[ ii ][ jj ].in_list() );
619  assert( ! narrow(0)[ jj ][ ii ].in_list() );
620  //narrow(1)[ ii ][ jjatno ].data() = iiwide[ jjatno ].data();
621  narrow(1)[ ii ].move_to_back( jj );
622  //narrow(0)[ jjatno ][ ii ].data() = wide(0)[ jjatno ][ ii ].data();
623  narrow(0)[ jj ].move_to_back( ii );
624  }
625  }
626  }
627  for ( Size ii = r2dat.wide_ood_list().head(); ii != 0; ii = r2dat.wide_ood_list()[ ii ].next() ) {
628  assert( r2dat.atom_status(ii) == wide_ood );
629  int ii_isH = r2dat.is_H( ii );
630  for ( Size jj = 1; jj <= r1.natoms(); ++jj ) {
631  if ( r1dat.atom_status(jj) == wide_ood ) continue; // already updated!
632  int jj_isH = r1dat.is_H( jj );
633  Real weight( 1.0 );
634  Size path_dist( 0 );
635  if ( cpfxn_->count( jj, ii, weight, path_dist ) ) {
636  Real d2w = r2dat.wide_coord( ii ).distance_squared( r1dat.wide_coord( jj ) );
637 #ifdef APL_TEMP_DEBUG
638  /// APL TEMP
639  ++n_wide_dist_evals;
640  ++n_update_dist_evals;
641  ++n_update_dist_evals_total;
642 #endif
643  if ( d2w < wcut2_[ ii_isH + jj_isH ] ) {
644  assert( ! wide(1)[ ii ][ jj ].in_list() ); // should have already been removed
645  assert( ! wide(0)[ jj ][ ii ].in_list() ); // should have already been removed
646  //wide(1)[ ii ][ jj ].data() = AtomNeighbor( r1.seqpos(), jj, path_dist, weight );
647  //wide(0)[ jj ][ ii ].data() = AtomNeighbor( r2.seqpos(), ii, path_dist, weight );
648  wide(1)[ ii ].move_to_back( jj );
649  wide(0)[ jj ].move_to_back( ii );
650  if ( r1dat.atom_status( jj ) < wide_ood ) {
651  Real d2n = r2dat.narrow_coord( ii ).distance_squared( r1dat.narrow_coord( jj ) );
652 #ifdef APL_TEMP_DEBUG
653  /// APL TEMP
654  ++n_wide_dist_evals;
655  ++n_update_dist_evals;
656  ++n_update_dist_evals_total;
657 #endif
658  if ( d2n < ncut2_[ ii_isH + jj_isH ] ) {
659  assert( ! narrow(1)[ ii ][ jj ].in_list() ); // should have already been removed
660  assert( ! narrow(0)[ jj ][ ii ].in_list() ); // should have already been removed
661  //narrow(1)[ ii ][ jj ].data() = wide(1)[ ii ][ jj ].data();
662  //narrow(0)[ jj ][ ii ].data() = wide(0)[ jj ][ ii ].data();
663  narrow(1)[ ii ].move_to_back( jj );
664  narrow(0)[ jj ].move_to_back( ii );
665  }
666  }
667  }
668  }
669  }
670  }
671 
672  //assert( accurate(
673  // heavy_heavy_dist_cutoff,
674  // heavy_hydrogen_dist_cutoff,
675  // hydrogen_hydrogen_dist_cutoff,
676  // r1, r2, r1dat, r2dat ) );
677 }
678 
679 
680 bool
681 ResiduePairNeighborList::accurate(
682  Real heavy_heavy_dist_cutoff,
683  Real heavy_hydrogen_dist_cutoff,
684  Real hydrogen_hydrogen_dist_cutoff,
685  conformation::Residue const & r1,
686  conformation::Residue const & r2,
687  ResidueNblistData const & r1dat,
688  ResidueNblistData const & r2dat
689 ) const
690 {
691 
692  for ( Size ii = 1; ii <= r1.natoms(); ++ii ) {
693  for ( Size jj = 1; jj <= r2.natoms(); ++jj ) {
694  Real weight( 1.0 );
695  Size path_dist( 0 );
696  if ( cpfxn_->count( ii, jj, weight, path_dist )) {
697  Real d2w = r1dat.wide_coord( ii ).distance_squared( r2dat.wide_coord( jj ) );
698  if ( d2w < wcut2_[ r1dat.is_H( ii ) + r2dat.is_H( jj ) ] ) {
699  assert( wide(0)[ ii ][ jj ].in_list() );
700  assert( wide(1)[ jj ][ ii ].in_list() );
701  } else {
702  assert( ! wide(0)[ ii ][ jj ].in_list() );
703  assert( ! wide(1)[ jj ][ ii ].in_list() );
704  }
705  Real d2n = r1dat.narrow_coord( ii ).distance_squared( r2dat.narrow_coord( jj ) );
706  if ( d2n < ncut2_[ r1dat.is_H( ii ) + r2dat.is_H( jj ) ] ) {
707  assert( narrow(0)[ ii ][ jj ].in_list() );
708  assert( narrow(1)[ jj ][ ii ].in_list() );
709  assert( wide(0)[ ii ][ jj ].in_list() );
710  assert( wide(1)[ jj ][ ii ].in_list() );
711  } else {
712  assert( ! narrow(0)[ ii ][ jj ].in_list() );
713  assert( ! narrow(1)[ jj ][ ii ].in_list() );
714  }
715  } else {
716  assert( ! narrow(0)[ ii ][ jj ].in_list() );
717  assert( ! narrow(1)[ jj ][ ii ].in_list() );
718  assert( ! wide(0)[ ii ][ jj ].in_list() );
719  assert( ! wide(1)[ jj ][ ii ].in_list() );
720  }
721  }
722  }
723  return true;
724 }
725 
726 
727 
728 /// @details Do not deallocate the space representing the atom-neighbors of either residue.
729 /// This is a time-saving technique to avoid the use of new and delete where possible.
730 void ResiduePairNeighborList::clear()
731 {
732  for ( Size ii = 1; ii <= res1_neighbors_.size(); ++ii ) res1_neighbors_[ ii ].clear();
733  for ( Size ii = 1; ii <= res2_neighbors_.size(); ++ii ) res2_neighbors_[ ii ].clear();
734 }
735 
736 /// @details This class does not hold the residue id as part of the AtomNeighbor for either residue.
737 /// That information must be available to the class that's using this data through some other means
738 void ResiduePairNeighborList::add_atom_neighbor(
739  Size ind1,
740  Size ind2,
741  Size path_distance,
742  Real weight,
743  Real weight_func
744 )
745 {
746  assert( ind1 <= res1_neighbors_.size() );
747  assert( ind2 <= res2_neighbors_.size() );
748  AtomNeighbor at2( 1, ind2, path_distance, weight, weight_func );
749  AtomNeighbor at1( 1, ind1, path_distance, weight, weight_func );
750  res1_neighbors_[ ind1 ].push_back( at2 );
751  res2_neighbors_[ ind2 ].push_back( at1 );
752 }
753 */
754 
757 
760 {
761  return new ResidueNblistData( *this );
762 }
763 
765  conformation::Residue const & res,
766  CountPairFunctionCOP cpfxn,
767  Real vvd2,
768  Real hvd2,
769  Real hhd2
770 )
771 {
772  atom_neighbors_.clear();
773 
774  if ( ! cpfxn ) return;
775 
776  utility::vector0< Real > cutoffs( 3 );
777  cutoffs[ 0 ] = vvd2;
778  cutoffs[ 1 ] = hvd2;
779  cutoffs[ 2 ] = hhd2;
780 
781  for ( Size ii = 1; ii < res.natoms(); ++ii ) {
782  int ii_isH = res.atom_is_hydrogen( ii );
783  for ( Size jj = ii+1; jj <= res.natoms(); ++jj ) {
784  int jj_isH = res.atom_is_hydrogen( jj );
785  Real weight( 1.0 );
786  Size path_dist( 0 );
787  if ( cpfxn->count( ii, jj, weight, path_dist ) ) {
788  Real d2 = res.xyz( ii ).distance_squared( res.xyz( jj ) );
789  if ( d2 < cutoffs[ ii_isH + jj_isH ] ) {
790  atom_neighbors_.push_back( SmallAtNb( ii, jj, weight ) );
791  }
792  }
793  }
794  }
795 }
796 
799 
801 
802 void
804  Real vvd2,
805  Real hvd2,
806  Real hhd2,
807  conformation::Residue const & r1,
808  conformation::Residue const & r2,
810 )
811 {
812  atom_neighbors_.clear();
813 
814  //std::cout << "ResiduePairNeighborList::initialize_from_residues " << r1.seqpos() << " " << r2.seqpos() << std::endl;
815 
816  utility::vector0< Real > cutoffs( 3 );
817  cutoffs[ 0 ] = vvd2;
818  cutoffs[ 1 ] = hvd2;
819  cutoffs[ 2 ] = hhd2;
820 
821  for ( Size ii = 1; ii <= r1.natoms(); ++ii ) {
822  int ii_isH = r1.atom_is_hydrogen( ii );
823  for ( Size jj = 1; jj <= r2.natoms(); ++jj ) {
824  int jj_isH = r2.atom_is_hydrogen( jj );
825  Real weight( 1.0 );
826  Size path_dist( 0 );
827  if ( cpfxn->count( ii, jj, weight, path_dist ) ) {
828  Real d2 = r1.xyz( ii ).distance_squared( r2.xyz( jj ) );
829  ///std::cout << " atoms " << ii << " " << jj << " " << r1.atom_name( ii ) << " " << r2.atom_name( jj )
830  /// << " d2: " << d2 << " d " << std::sqrt( d2 ) << " cutoff2:" << cutoffs[ ii_isH + jj_isH ]
831  /// << " cutoff " << std::sqrt( cutoffs[ ii_isH + jj_isH ] ) << std::endl;
832  if ( d2 < cutoffs[ ii_isH + jj_isH ] ) {
833  atom_neighbors_.push_back( SmallAtNb( ii, jj, weight ) );
834  }
835  }
836  }
837  }
838 }
839 
840 
841 }
842 }