Rosetta 3.5
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
OccupiedSpaceHash.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 // :noTabs=false:tabSize=4:indentSize=4:
4 //
5 // (c) Copyright Rosetta Commons Member Institutions.
6 // (c) This file is part of the Rosetta software suite and is made available under license.
7 // (c) The Rosetta software is developed by the contributing members of the Rosetta Commons.
8 // (c) For more information, see http://www.rosettacommons.org. Questions about this can be
9 // (c) addressed to University of Washington UW TechTransfer, email: license@u.washington.edu.
10 
11 /// @file protocols/match/OccupiedSpaceHash.cc
12 /// @brief Declaration for classes in 6D hasher
13 /// @author Alex Zanghellini (zanghell@u.washington.edu)
14 /// @author Andrew Leaver-Fay (aleaverfay@gmail.com), porting to mini
15 
16 // Unit headers
18 
19 // Package headers
22 
23 //numeric headers
24 #include <numeric/geometry/hashing/SixDHasher.hh>
25 
26 // Utility headers
27 // AUTO-REMOVED #include <utility/LexicographicalIterator.hh>
28 
29 // C++ headers
30 #include <fstream>
31 
32 #include <utility/vector1.hh>
33 
34 
35 namespace protocols {
36 namespace match {
37 
38 OccupiedSpaceHash::OccupiedSpaceHash() : initialized_( false ), revision_id_( 1 ) {}
40 
41 void
43  BoundingBox const & bb
44 )
45 {
46  assert( ! initialized_ );
47  bb_ = bb;
48 }
49 
50 void
52 {
53  assert( ! initialized_ );
54  assert( bin_width > 0 );
55  Real half_witdh = 0.5 * bin_width;
56  for ( Size ii = 1; ii <= 3; ++ii ) {
57  xyz_bin_widths_[ ii ] = bin_width;
58  xyz_bin_halfwidths_[ ii ] = half_witdh;
59  }
60 }
61 
62 void
64 {
65  assert( ! initialized_ );
66  assert( bin_width_degrees > 0 );
67  Real half_width = 0.5 * bin_width_degrees;
68  for ( Size ii = 1; ii <= 3; ++ii ) {
69  euler_bin_widths_[ ii ] = bin_width_degrees;
70  euler_bin_halfwidths_[ ii ] = half_width;
71  }
72 }
73 
74 void
76 {
77  assert( ! initialized_ );
78  for ( Size ii = 1; ii <= 3; ++ii ) {
79  assert( bin_widths( ii ) > 0 );
80  xyz_bin_widths_[ ii ] = bin_widths( ii );
81  xyz_bin_halfwidths_[ ii ] = 0.5 * bin_widths( ii );
82  }
83 
84 }
85 
86 void
88 {
89  assert( ! initialized_ );
90  for ( Size ii = 1; ii <= 3; ++ii ) {
91  assert( euler_bin_widths( ii ) > 0 );
92  euler_bin_widths_[ ii ] = euler_bin_widths( ii );
93  euler_bin_halfwidths_[ ii ] = 0.5 * euler_bin_widths( ii );
94  }
95 }
96 
97 //void
98 //OccupiedSpaceHash::set_expected_hash_count()
99 //{
100 //}
101 
102 void
104 {
105  assert( ! initialized_ );
106 
107  initialized_ = true;
108 
109  for ( Size ii = 1; ii <= 3; ++ii ) {
110  n_xyz_bins_[ ii ] = static_cast< Size > (( bb_.upper()(ii) - bb_.lower()(ii) ) / xyz_bin_widths_[ ii ] );
111  if ( bb_.lower()(ii) + n_xyz_bins_[ ii ]*xyz_bin_widths_[ ii ] < bb_.upper()( ii ) ) {
112  ++n_xyz_bins_[ ii ];
113  }
114  }
115 
116  for ( Size ii = 1; ii <= 3; ++ii ) {
117  Real range = ii == 3 ? 180 : 360;
118  n_euler_bins_[ ii ] = static_cast< Size > ( range / euler_bin_widths_[ ii ] );
119  if ( n_euler_bins_[ ii ] * euler_bin_widths_[ ii ] < range ) {
120  n_euler_bins_[ ii ];
121  }
122  }
123 
124  dim_prods_[ 6 ] = 1;
125  dim_prods_[ 5 ] = n_euler_bins_[ 3 ];
126  dim_prods_[ 4 ] = n_euler_bins_[ 2 ] * dim_prods_[ 5 ];
127  dim_prods_[ 3 ] = n_euler_bins_[ 1 ] * dim_prods_[ 4 ];
128  dim_prods_[ 2 ] = n_xyz_bins_[ 3 ] * dim_prods_[ 3 ];
129  dim_prods_[ 1 ] = n_xyz_bins_[ 2 ] * dim_prods_[ 2 ];
130 
132  threeD_projection_->set_bounding_box( bb_ );
133  threeD_projection_->set_bin_width( xyz_bin_widths_[ 1 ] );
134 }
135 
136 void
138 {
139  assert( initialized_ );
140 
141  if ( revision_id_ == 1 ) { ++revision_id_; } /// round 1 is over.
142 
143  Vector point( Vector( geom[ 1 ], geom[ 2 ], geom[ 3 ] ));
144  if ( ! bb_.contains( point ) ) return;
145 
148 
149  numeric::geometry::hashing::Bin6D bin;
150  Size pos;
151  boost::uint64_t bin_index;
152  while ( ! voxiter.at_end() ) {
153  voxiter.get_bin_and_pos( bin, pos );
154  bin_index = calc_bin_index( bin );
155  ActiveVoxelSet::iterator iter = hash_.find( bin_index );
156  if ( iter == hash_.end() ) {
157  hash_.insert( std::make_pair( bin_index, bitmask_for_position( pos ) ));
158  } else {
159  iter->second |= bitmask_for_position( pos );
160  }
161  ++voxiter;
162  }
163 
164  project_point_to_3d( geom );
165 }
166 
167 void
169 {
170  /// Increment the revision id. This signals to observing ClassicMatchAlgorithms that
171  /// hits generated in previous rounds might no-longer be viable; after this round
172  /// any hit such that none of it's 64 voxels recieved any hits from this round is unable
173  /// to yield a match.
174  ///
175  /// Rounds that use secondary matching on upstream residues will not
176  ++revision_id_;
177 
178  for ( ActiveVoxelSet::iterator iter = hash_.begin(), iter_end = hash_.end();
179  iter != iter_end; ++iter ) {
180  iter->second = 0;
181  }
182 
184 }
185 
186 void
188 {
189  threeD_projection_->clear();
190 }
191 
192 
193 bool
195 {
196  bool still_matchable( match_possible_for_hit_geometry( geom ));
197  if ( still_matchable ) {
198  project_point_to_3d( geom );
199  }
200  return still_matchable;
201 }
202 
203 void
205 {
206  assert( initialized_ );
207  Vector point( Vector( geom[ 1 ], geom[ 2 ], geom[ 3 ] ));
208  if ( ! bb_.contains( point ) ) return;
209 
212 
213  numeric::geometry::hashing::Bin6D bin;
214  Size pos;
215  boost::uint64_t bin_index;
216  while ( ! voxiter.at_end() ) {
217  voxiter.get_bin_and_pos( bin, pos );
218  bin_index = calc_bin_index( bin );
219  ActiveVoxelSet::iterator iter = hash_.find( bin_index );
220  if ( iter != hash_.end() ) {
221  boost::uint64_t mask = bitmask_for_position( pos );
222  if ( ! (iter->second & mask) ) {
223  iter->second |= mask;
224  }
225  }
226  ++voxiter;
227  }
228 
229  project_point_to_3d( geom );
230 }
231 
232 /// @details It must be safe for multiple threads to call function simultaneously
233 bool
235 {
236  using namespace utility;
237 
238  assert( initialized_ );
239  Vector point( Vector( geom[ 1 ], geom[ 2 ], geom[ 3 ] ));
240  if ( ! bb_.contains( point ) ) return false;
241 
242  /// Note, in the first round, the occupied space hash is empty. Hits have not yet
243  /// been inserted into it. Therefore, the purpose of the check in the first round
244  /// is to ensure the hit lies inside the bounding box.
245  if ( revision_id_ == 1 ) return true;
246 
247  if ( ! threeD_projection_->occupied( point ) ) return false;
248 
251 
252  numeric::geometry::hashing::Bin6D bin;
253  Size pos;
254  boost::uint64_t bin_index;
255  while ( ! voxiter.at_end() ) {
256  voxiter.get_bin_and_pos( bin, pos );
257  bin_index = calc_bin_index( bin );
258  ActiveVoxelSet::const_iterator iter = hash_.find( bin_index );
259  if ( iter != hash_.end() && iter->second & bitmask_for_position( pos ) ) {
260  return true;
261  }
262  ++voxiter;
263  }
264  return false;
265 
266 /* for ( Size ii = 1; ii <= N_HASH_MAPS; ++ii ) {
267  if ( hashes_[ ii ].first->contains( geom ) ) {
268  boost::uint64_t bin_index = hashes_[ ii ].first->bin_index( geom );
269  ActiveVoxelSet::const_iterator iter = hashes_[ ii ].second.find( bin_index );
270  if ( iter != hashes_[ ii ].second.end() ) {
271  //if ( ! threeD_projection_->occupied( point ) ) {
272  // std::cout << "point is not active?" << point.x() << " " << point.y() << " " << point.z() << std::endl;
273  //}
274  return true;
275  }
276  }
277  }
278 
279  /// None of the 64 bins was already occupied by this geometry; a match cannot be found with this hit!
280  return false;*/
281 }
282 
283 void
285 {
286  assert( initialized_ );
287  //threeD_projection_->clear();
288 
289  for ( ActiveVoxelSet::iterator
290  iter = hash_.begin(),
291  iter_end = hash_.end();
292  iter != iter_end; /* no increment */ ) {
293  ActiveVoxelSet::iterator iter_next = iter;
294  ++iter_next;
295  if ( iter->second == 0 ) {
296  hash_.erase( iter );
297  }
298  iter = iter_next;
299  }
300 
301 }
302 
303 void
305 {
308  std::ofstream fout;
309  fout.open( kin_file_name.c_str() );
310  writer.write_grid_to_kinemage( fout, "occspace", *threeD_projection_ );
311  fout.close();
312 }
313 
316 {
317  return revision_id_;
318 }
319 
320 
321 void
323 {
324 /*
325  Vector point( Vector( geom[ 1 ], geom[ 2 ], geom[ 3 ] ));
326 
327  Vector lower_bound( point ), upper_bound( point );
328  for ( Size ii = 1; ii <= 3; ++ii ) lower_bound( ii ) -= xyz_width_root3_[ ii ];
329  for ( Size ii = 1; ii <= 3; ++ii ) if ( lower_bound( ii ) < bb_.lower()( ii ) ) lower_bound( ii ) = bb_.lower()( ii );
330  for ( Size ii = 1; ii <= 3; ++ii ) upper_bound( ii ) += xyz_width_root3_[ ii ];
331  for ( Size ii = 1; ii <= 3; ++ii ) if ( upper_bound( ii ) < bb_.upper()( ii ) ) upper_bound( ii ) = bb_.upper()( ii );
332 
333  threeD_projection_->or_by_box_liberal( BoundingBox( lower_bound, upper_bound ) );
334 */
335  Vector point( Vector( geom[ 1 ], geom[ 2 ], geom[ 3 ] ));
336  assert( bb_.contains( point ));
337 
338  Vector local = point - bb_.lower();
339  Vector lower = bb_.lower();
340  Vector upper = bb_.lower();
341 
342  Vector local_lower;
343  for ( Size ii = 1; ii <= 3; ++ii ) {
344  local_lower( ii ) = static_cast< Size > ( local( ii ) / xyz_bin_widths_[ ii ] ) * xyz_bin_widths_[ ii ];
345  }
346  lower += local_lower;
347  upper += local_lower;
348  for ( Size ii = 1; ii <= 3; ++ii ) {
349  upper( ii ) += xyz_bin_widths_[ ii ];
350  }
351 
352  for ( Size ii = 1; ii <= 3; ++ii ) {
353  if ( point( ii ) - lower( ii ) > 0.5 ) {
354  upper( ii ) += 0.5 * xyz_bin_widths_[ ii ];
355  } else {
356  lower( ii ) -= 0.5 * xyz_bin_widths_[ ii ];
357  }
358  }
359  for ( Size ii = 1; ii <= 3; ++ii ) if ( lower( ii ) < bb_.lower()( ii ) ) lower( ii ) = bb_.lower()( ii );
360  for ( Size ii = 1; ii <= 3; ++ii ) if ( upper( ii ) > bb_.upper()( ii ) ) upper( ii ) = bb_.upper()( ii );
361 
362 
363  threeD_projection_->or_by_box_liberal( BoundingBox( lower, upper ) );
364 
365 }
366 
367 /// @details return the 64-bit bitmask for a particular bit -- numbered in increasing order
368 /// from right to left.
369 boost::uint64_t
371  assert( pos > 0 && pos <= 64 );
372 
373  switch ( pos ) {
374  case 1: return 0x01;
375  case 2: return 0x02;
376  case 3: return 0x04;
377  case 4: return 0x08;
378  case 5: return 0x10;
379  case 6: return 0x20;
380  case 7: return 0x40;
381  case 8: return 0x80;
382 
383  case 9: return 0x0100;
384  case 10: return 0x0200;
385  case 11: return 0x0400;
386  case 12: return 0x0800;
387  case 13: return 0x1000;
388  case 14: return 0x2000;
389  case 15: return 0x4000;
390  case 16: return 0x8000;
391 
392  case 17: return 0x010000;
393  case 18: return 0x020000;
394  case 19: return 0x040000;
395  case 20: return 0x080000;
396  case 21: return 0x100000;
397  case 22: return 0x200000;
398  case 23: return 0x400000;
399  case 24: return 0x800000;
400 
401  case 25: return 0x01000000;
402  case 26: return 0x02000000;
403  case 27: return 0x04000000;
404  case 28: return 0x08000000;
405  case 29: return 0x10000000;
406  case 30: return 0x20000000;
407  case 31: return 0x40000000;
408  case 32: return 0x80000000;
409 
410  case 33: return 0x0100000000LL;
411  case 34: return 0x0200000000LL;
412  case 35: return 0x0400000000LL;
413  case 36: return 0x0800000000LL;
414  case 37: return 0x1000000000LL;
415  case 38: return 0x2000000000LL;
416  case 39: return 0x4000000000LL;
417  case 40: return 0x8000000000LL;
418 
419  case 41: return 0x010000000000LL;
420  case 42: return 0x020000000000LL;
421  case 43: return 0x040000000000LL;
422  case 44: return 0x080000000000LL;
423  case 45: return 0x100000000000LL;
424  case 46: return 0x200000000000LL;
425  case 47: return 0x400000000000LL;
426  case 48: return 0x800000000000LL;
427 
428  case 49: return 0x01000000000000LL;
429  case 50: return 0x02000000000000LL;
430  case 51: return 0x04000000000000LL;
431  case 52: return 0x08000000000000LL;
432  case 53: return 0x10000000000000LL;
433  case 54: return 0x20000000000000LL;
434  case 55: return 0x40000000000000LL;
435  case 56: return 0x80000000000000LL;
436 
437  case 57: return 0x0100000000000000LL;
438  case 58: return 0x0200000000000000LL;
439  case 59: return 0x0400000000000000LL;
440  case 60: return 0x0800000000000000LL;
441  case 61: return 0x1000000000000000LL;
442  case 62: return 0x2000000000000000LL;
443  case 63: return 0x4000000000000000LL;
444  case 64: return 0x8000000000000000LL;
445  default: break;
446  }
447  utility_exit_with_message( "Critical Error in OccupiedSpaceHash::bitmask_for_position. position outside of range [1 .. 64]. Cannot continue." );
448  return 0;
449 }
450 
451 boost::uint64_t
452 OccupiedSpaceHash::calc_bin_index( numeric::geometry::hashing::Bin6D const & bin ) const
453 {
454  boost::uint64_t index( 0 );
455  for ( Size ii = 1; ii <= 6; ++ii ) {
456  index += bin[ ii ] * dim_prods_[ ii ];
457  }
458  return index;
459 }
460 
461 
462 
463 }
464 }
465