Rosetta 3.5
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
LoopHashMap.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 protocols/loops/LoopHashMap.cc
11 /// @brief
12 /// @author Mike Tyka
13 
14 
15 
16 // libRosetta headers
22 
23 // AUTO-REMOVED #include <boost/cstdint.hpp>
24 #include <boost/unordered_map.hpp>
25 // AUTO-REMOVED #include <core/chemical/ResidueTypeSet.hh>
26 
27 // AUTO-REMOVED #include <core/chemical/ChemicalManager.hh>
29 #include <core/pose/util.hh>
30 #include <core/kinematics/Jump.hh>
31 #include <core/kinematics/RT.hh>
32 // AUTO-REMOVED #include <core/import_pose/pose_stream/util.hh>
33 // AUTO-REMOVED #include <core/io/pdb/pose_io.hh>
34 #include <core/pose/Pose.hh>
36 // AUTO-REMOVED #include <core/conformation/ResidueFactory.hh>
37 // AUTO-REMOVED #include <core/scoring/constraints/util.hh>
38 #include <basic/Tracer.hh>
39 #include <basic/options/option.hh>
40 #include <basic/options/keys/lh.OptionKeys.gen.hh>
41 
42 #include <numeric/HomogeneousTransform.hh>
43 //#include <protocols/match/Hit.fwd.hh>
44 // AUTO-REMOVED #include <protocols/match/Hit.hh>
45 // AUTO-REMOVED #include <protocols/moves/Mover.hh>
46 #include <utility/excn/Exceptions.hh>
47 #include <utility/exit.hh>
48 #include <utility/fixedsizearray1.hh>
49 #include <utility/pointer/owning_ptr.hh>
50 
51 #include <numeric/angle.functions.hh>
52 #include <numeric/geometry/hashing/SixDHasher.hh>
53 
54 // C++ headers
55 #include <cstdio>
56 
57 #include <iostream>
58 #include <fstream>
59 #include <string>
60 #include <sstream>
61 // AUTO-REMOVED #include <boost/algorithm/string.hpp>
62 #include <boost/lexical_cast.hpp>
63 
64 
66 #include <utility/vector1.hh>
67 
68 #if defined(WIN32) || defined(__CYGWIN__)
69  #include <ctime>
70 #endif
71 
72 
73 
74 using namespace protocols::moves;
75 using namespace core::scoring;
76 using namespace core;
77 using namespace core::pose;
78 using namespace conformation;
79 using namespace kinematics;
80 using namespace protocols::frag_picker;
81 
82 
83 
84 
85 
86 namespace protocols {
87 namespace loophash {
88 
89 
90 
91 
92 static basic::Tracer TR("LoopHashMap");
93 
94 
95 
96 
97 /// @brief This takes a pose and two residue positions and determines the rigid body transform of the Leap described by those two residues.
98 /// Returns true is successful or false if something went haywire and one should just ignore this loop (this can happen at the ends)
100  using namespace core;
101  using namespace core::pose;
102  using namespace conformation;
103  using namespace kinematics;
104  using namespace numeric::geometry::hashing;
105 
106  core::pose::Pose pose = orig_pose;
107 
108  //fpd vrt/ligand trim
109  core::Size nres = pose.total_residue();
110  while (!pose.residue_type(nres).is_polymer()) nres--;
111 
112  // get current cutpoints; don't try to connect these
113  utility::vector1< Size > cuts_in = pose.fold_tree().cutpoints();
114  std::sort( cuts_in.begin(), cuts_in.end() );
115 
116  // bail if (ir,jr) crosses a cut
117  for (Size i=1; i<=cuts_in.size(); ++i) {
118  if (cuts_in[i]<=jr && cuts_in[i]>=ir) {
119  TR.Error << "ERROR -- residue range crosses cut IR: " << ir << " JR: " << jr << " CUT: " << cuts_in[i] << std::endl;
120  return false;
121  }
122  //fpd insertions one position after the cut seem not to work ...
123  //fpd perhaps if the foldtree for the local segment were reversed this might be ok
124  if (cuts_in[i]==ir-1) {
125  TR.Error << "ERROR -- startres immediately follows cut IR: " << ir << " CUT: " << cuts_in[i] << std::endl;
126  return false;
127  }
128  }
129 
130  // Create a fake foldtree with a jump from ir to jr, and the cutpoint just before jr. From that extract the
131  // rigid body transfer. This is fairly hacky, but actually works v reliably and is easy to understand, without
132  // having to mess deeply with the fold tree.
133  // FoldTree f;
134  // Size cutpoint= jr-1;
135  // f.add_edge( 1, ir, Edge::PEPTIDE );
136  // f.add_edge( ir, cutpoint, Edge::PEPTIDE );
137  // f.add_edge( cutpoint + 1, jr, Edge::PEPTIDE );
138  // f.add_edge( jr, nres , Edge::PEPTIDE );
139  // f.add_edge( ir, jr, 1 ); // this is the jump !!
140 
141  //fpd handle multiple chains/chainbreaks
142  FoldTree f;
143  core::Size last_cut=0, jump_num=2;
144  Size cutpoint= jr-1;
145  for (Size i=1; i<=cuts_in.size(); ++i) {
146  if (cuts_in[i] >= nres) break;
147  if (cutpoint > last_cut && cutpoint < cuts_in[i]) {
148  f.add_edge( last_cut+1, ir, Edge::PEPTIDE );
149  f.add_edge( ir, cutpoint, Edge::PEPTIDE );
150  f.add_edge( cutpoint + 1, jr, Edge::PEPTIDE );
151  f.add_edge( jr, cuts_in[i] , Edge::PEPTIDE );
152  f.add_edge( ir, jr, 1 ); // this is the jump !!
153  if (last_cut!=0) f.add_edge( 1, last_cut+1, jump_num++);
154  } else {
155  f.add_edge( last_cut+1, cuts_in[i], Edge::PEPTIDE );
156  if (last_cut!=0) f.add_edge( 1, last_cut+1, jump_num++);
157  }
158  last_cut = cuts_in[i];
159  }
160  if (last_cut+1 <= nres) {
161  if (cutpoint > last_cut && cutpoint < nres) {
162  f.add_edge( last_cut+1, ir, Edge::PEPTIDE );
163  f.add_edge( ir, cutpoint, Edge::PEPTIDE );
164  f.add_edge( cutpoint + 1, jr, Edge::PEPTIDE );
165  f.add_edge( jr, nres , Edge::PEPTIDE );
166  f.add_edge( ir, jr, 1 ); // this is the jump !!
167  if (last_cut!=0) f.add_edge( 1, last_cut+1, jump_num++);
168  } else {
169  f.add_edge( last_cut+1, nres, Edge::PEPTIDE );
170  if (last_cut!=0) f.add_edge( 1, last_cut+1, jump_num++);
171  }
172  }
173  for (core::Size i=nres+1; i<=pose.total_residue(); ++i)
174  f.add_edge( 1, i, jump_num++ ); // additional jumps
175 
176  core::Size theroot = 1;
177  if( ir == 1 ) theroot = pose.total_residue();
178  if( orig_pose.residue_type( orig_pose.fold_tree().root() ).aa() == core::chemical::aa_vrt ) theroot = orig_pose.fold_tree().root(); //fpd
179  if( f.reorder(theroot) == false ){
180  TR.Error << "ERROR During reordering of fold tree - am ignoring this LOOP ! bailing: The root: " << theroot << " NRES " << pose.total_residue() << " IR: " << ir << " JR: " << jr << std::endl;
181  return false; // continuing leads to a segfault - instead ignore this loop !
182  }
183 
184  // Apply this new foldtree to the pose.
185  pose.fold_tree( f );
186 
187  // Now extract the rigid body transform!
188  Jump myjump;
189  myjump = pose.jump( 1 );
190 
191  // Aha, now you have the RT (RigidbodyTransform)
192  RT rt = myjump.rt();
193 
194  // Create a 6 value representation: (just change the data format)
195  numeric::HomogeneousTransform< Real > ht( rt.get_rotation() , rt.get_translation() );
196  numeric::xyzVector < Real > euler_angles = ht.euler_angles_rad();
197 
198  rt_6[1] = rt.get_translation().x();
199  rt_6[2] = rt.get_translation().y();
200  rt_6[3] = rt.get_translation().z();
201  rt_6[4] = euler_angles.x()*180.0/numeric::constants::d::pi;
202  rt_6[5] = euler_angles.y()*180.0/numeric::constants::d::pi;
203  rt_6[6] = euler_angles.z()*180.0/numeric::constants::d::pi;
204 
205  // indicate success
206  return true;
207 }
208 
209 
210 
211 /// @brief This takes a pose and two residue positions and determines the rigid body transform of the Leap described by those two residues
212 /// THe difference between this and the get_rt_over_leap function is that this version doesnt make a copy of the pose which makes it faster.
213 /// However this means that the pose passed cannot be a const pose, even though the function restores the fold tree afterwards..
215  using namespace core;
216  using namespace core::pose;
217  using namespace conformation;
218  using namespace kinematics;
219  using namespace numeric::geometry::hashing;
220 
221  core::Size newroot=0;
222  if( pose.residue_type( pose.fold_tree().root() ).aa() == core::chemical::aa_vrt ) newroot = pose.fold_tree().root();
223 
224  //fpd vrt/ligand trim
225  core::Size nres = pose.total_residue();
226  while (!pose.residue_type(nres).is_polymer()) nres--;
227 
228  // get current cutpoints; don't try to connect these
229  utility::vector1< Size > cuts_in = pose.fold_tree().cutpoints();
230  std::sort( cuts_in.begin(), cuts_in.end() );
231 
232  // bail if (ir,jr) crosses a cut
233  for (Size i=1; i<=cuts_in.size(); ++i) {
234  if (cuts_in[i]<=jr && cuts_in[i]>=ir) {
235  TR.Error << "ERROR -- residue range crosses cut IR: " << ir << " JR: " << jr << " CUT: " << cuts_in[i] << std::endl;
236  return false;
237  }
238  //fpd insertions one position after the cut seem not to work ...
239  //fpd perhaps if the foldtree for the local segment were reversed this might be ok
240  if (cuts_in[i]==ir-1) {
241  TR.Error << "ERROR -- startres immediately follows cut IR: " << ir << " CUT: " << cuts_in[i] << std::endl;
242  return false;
243  }
244  }
245 
246  // Create a fake foldtree with a jump from ir to jr, and the cutpoint just before jr. From that extract the
247  // rigid body transfer. This is fairly hacky, but actually works v reliably and is easy to understand, without
248  // having to mess deeply with the fold tree.
249  // FoldTree f;
250  // Size cutpoint= jr-1;
251  // f.add_edge( 1, ir, Edge::PEPTIDE );
252  // f.add_edge( ir, cutpoint, Edge::PEPTIDE );
253  // f.add_edge( cutpoint + 1, jr, Edge::PEPTIDE );
254  // f.add_edge( jr, nres , Edge::PEPTIDE );
255  // f.add_edge( ir, jr, 1 ); // this is the jump !!
256 
257  //fpd handle multiple chains/chainbreaks
258  FoldTree f, f_orig=pose.fold_tree();
259  core::Size last_cut=0, jump_num=2;
260  Size cutpoint= jr-1;
261  for (Size i=1; i<=cuts_in.size(); ++i) {
262  if (cuts_in[i] >= nres) break;
263  if (cutpoint > last_cut && cutpoint < cuts_in[i]) {
264  f.add_edge( last_cut+1, ir, Edge::PEPTIDE );
265  f.add_edge( ir, cutpoint, Edge::PEPTIDE );
266  f.add_edge( cutpoint + 1, jr, Edge::PEPTIDE );
267  f.add_edge( jr, cuts_in[i] , Edge::PEPTIDE );
268  f.add_edge( ir, jr, 1 ); // this is the jump !!
269  if (last_cut!=0) f.add_edge( 1, last_cut+1, jump_num++);
270  } else {
271  f.add_edge( last_cut+1, cuts_in[i], Edge::PEPTIDE );
272  if (last_cut!=0) f.add_edge( 1, last_cut+1, jump_num++);
273  }
274  last_cut = cuts_in[i];
275  }
276  if (last_cut+1 <= nres) {
277  if (cutpoint > last_cut && cutpoint < nres) {
278  f.add_edge( last_cut+1, ir, Edge::PEPTIDE );
279  f.add_edge( ir, cutpoint, Edge::PEPTIDE );
280  f.add_edge( cutpoint + 1, jr, Edge::PEPTIDE );
281  f.add_edge( jr, nres , Edge::PEPTIDE );
282  f.add_edge( ir, jr, 1 ); // this is the jump !!
283  if (last_cut!=0) f.add_edge( 1, last_cut+1, jump_num++);
284  } else {
285  f.add_edge( last_cut+1, nres, Edge::PEPTIDE );
286  if (last_cut!=0) f.add_edge( 1, last_cut+1, jump_num++);
287  }
288  }
289  for (core::Size i=nres+1; i<=pose.total_residue(); ++i)
290  f.add_edge( 1, i, jump_num++ ); // additional jumps
291 
292  core::Size theroot = 1;
293  if( ir == 1 ) theroot = pose.total_residue();
294  if( newroot>0 ) theroot = newroot; //fpd
295  if( f.reorder(theroot) == false ){
296  TR.Error << "ERROR During reordering of fold tree - am ignoring this LOOP ! bailing: The root: " << theroot << " NRES " << pose.total_residue() << " IR: " << ir << " JR: " << jr << std::endl;
297  return false; // continuing leads to a segfault - instead ignore this loop !
298  }
299 
300  // Apply this new foldtree to the pose.
301  pose.fold_tree( f );
302 
303  // Now extract the rigid body transform!
304  Jump myjump;
305  myjump = pose.jump( 1 );
306  RT rt = myjump.rt();
307 
308  // restore prev foldtree
309  pose.fold_tree( f_orig );
310 
311  // TR.Info << "R: " << ir << " " << jr << rt << std::endl;
312 
313  // Create a 6 value representation:
314 
315  numeric::HomogeneousTransform< Real > ht( rt.get_rotation() , rt.get_translation() );
316  numeric::xyzVector < Real > euler_angles = ht.euler_angles_rad();
317 
318 
319  rt_6[1] = rt.get_translation().x();
320  rt_6[2] = rt.get_translation().y();
321  rt_6[3] = rt.get_translation().z();
322  rt_6[4] = euler_angles.x()*180.0/numeric::constants::d::pi;
323  rt_6[5] = euler_angles.y()*180.0/numeric::constants::d::pi;
324  rt_6[6] = euler_angles.z()*180.0/numeric::constants::d::pi;
325 
326  return true;
327 }
328 
329 bool
331  core::pose::Pose const & pose,
332  core::Size ir,
333  core::Size jr,
335 ){
336  using core::id::AtomID;
337 
338  if(!pose.residue(ir).is_protein()) return false;
339  if(!pose.residue(jr).is_protein()) return false;
340 
341  core::id::StubID id1( AtomID(2,ir), AtomID(1,ir), AtomID( 3 ,ir-1) );
342  core::id::StubID id2( AtomID(2,jr), AtomID(1,jr), AtomID( pose.residue(jr).atom_index("H") ,jr ) );
343 
344  RT rt = pose.conformation().get_stub_transform(id1,id2);
345 
346  numeric::HomogeneousTransform< Real > ht( rt.get_rotation() , rt.get_translation() );
347  numeric::xyzVector < Real > euler_angles = ht.euler_angles_rad();
348 
349  rt_6[1] = rt.get_translation().x();
350  rt_6[2] = rt.get_translation().y();
351  rt_6[3] = rt.get_translation().z();
352  rt_6[4] = euler_angles.x()*180.0/numeric::constants::d::pi;
353  rt_6[5] = euler_angles.y()*180.0/numeric::constants::d::pi;
354  rt_6[6] = euler_angles.z()*180.0/numeric::constants::d::pi;
355 
356  return true;
357 }
358 
359 
360 
361 LoopHashMap::LoopHashMap( core::Size loop_size){
362  loop_size_ = loop_size;
363  setup(loop_size);
364 }
365 
366 void LoopHashMap::mem_foot_print(){
367  TR << "loopdb_: " << loopdb_.size() << " Size: " << loopdb_.size() * sizeof( LeapIndex ) << std::endl;
368  TR << "BackboneIndexMap: " << backbone_index_map_.size() << " Size: " << backbone_index_map_.size() * (sizeof(boost::uint64_t) + sizeof(core::Size) ) << std::endl;
369 }
370 
371 void LoopHashMap::sort() {
372  std::sort( loopdb_.begin(), loopdb_.end(), by_index() );
373 }
374 
375 void
376 LoopHashMap::setup( core::Size loop_size)
377 {
378  loop_size_ = loop_size;
379 
380  if( loop_size > 1 ){
381  // only show this if this class is being set up with a meaningful parameter. Loop_size == 1 means it was called without an argument to the constructor and
382  // so its just an intermediate data structure.
383  TR.Info << "Setting up hash_: Size: " << loop_size << std::endl;
384 
385  }
386 
387  BoundingBox bounding_box( core::Vector(
388  -HASH_POSITION_GRID_BASE*(int)loop_size,
389  -HASH_POSITION_GRID_BASE*(int)loop_size,
390  -HASH_POSITION_GRID_BASE*(int)loop_size
391  ),
392  core::Vector(
393  HASH_POSITION_GRID_BASE*(int)loop_size,
394  HASH_POSITION_GRID_BASE*(int)loop_size,
395  HASH_POSITION_GRID_BASE*(int)loop_size
396  ) );
397  numeric::geometry::hashing::Size3 euler_offsets;
398  euler_offsets[1] = 0;
399  euler_offsets[2] = 0;
400  euler_offsets[3] = 0;
402 
403  core::Real space_multiplier = 0.2;
404  core::Real angle_multiplier = 15.0/6.0;
405 
406  using namespace basic::options;
407  using namespace basic::options::OptionKeys;
408 
409  if( option[ lh::grid_space_multiplier].user() ) {
410  space_multiplier = option[ lh::grid_space_multiplier]();
411  }
412  if( option[ lh::grid_angle_multiplier].user() ) {
413  angle_multiplier = option[ lh::grid_angle_multiplier]();
414  }
415 
416  bin_widths[1] = space_multiplier*loop_size;
417  bin_widths[2] = space_multiplier*loop_size;
418  bin_widths[3] = space_multiplier*loop_size;
419  bin_widths[4] = angle_multiplier*loop_size;
420  bin_widths[5] = angle_multiplier*loop_size;
421  bin_widths[6] = angle_multiplier*loop_size;
422 
423  hash_ = new numeric::geometry::hashing::SixDCoordinateBinner( bounding_box, euler_offsets, bin_widths );
424  // initialize the radial tree
425  hash_->tree_init(option[lh::max_radius]());
426 }
427 
428 void
429 LoopHashMap::add_legacyleap( const LegacyLeapIndex & legacyleap_index)
430 {
432  rt_6[1] = legacyleap_index.vecx;
433  rt_6[2] = legacyleap_index.vecy;
434  rt_6[3] = legacyleap_index.vecz;
435  rt_6[4] = legacyleap_index.rotx;
436  rt_6[5] = legacyleap_index.roty;
437  rt_6[6] = legacyleap_index.rotz;
438  LeapIndex leap_index;
439  leap_index.index = 0;
440  leap_index.offset = legacyleap_index.ba;
441  add_leap( leap_index, rt_6 );
442 }
443 
444 void LoopHashMap::add_leap( const LeapIndex &leap_index, boost::uint64_t key ) {
445  core::Size cpindex = loopdb_.size();
446  loopdb_.push_back( leap_index );
447  // No check to see if it is in hash because this data is already processed
448  backbone_index_map_.insert( std::make_pair( key, cpindex ));
449 }
450 
451 void LoopHashMap::add_leap( const LeapIndex &leap_index, numeric::geometry::hashing::Real6 & transform ){
452  core::Size cpindex = loopdb_.size();
453  loopdb_.push_back( leap_index );
455  rt_6[1] = transform[1];
456  rt_6[2] = transform[2];
457  rt_6[3] = transform[3];
458  rt_6[4] = transform[4];
459  rt_6[5] = transform[5];
460  rt_6[6] = transform[6];
461  while( rt_6[ 4 ] < 0.0 ) rt_6[ 4 ] += 360.0;
462  while( rt_6[ 4 ] >= 360.0 ) rt_6[ 4 ] -= 360.0;
463  while( rt_6[ 5 ] < 0.0 ) rt_6[ 5 ] += 360.0;
464  while( rt_6[ 5 ] >= 360.0 ) rt_6[ 5 ] -= 360.0;
465  while( rt_6[ 6 ] < 0.0 ) rt_6[ 6 ] += 180.0;
466  while( rt_6[ 6 ] > 180.0 ) rt_6[ 6 ] -= 180.0;
467  if( !( rt_6[ 4 ] >= 0.0 && rt_6[ 4 ] < 360.0 )) { std::cerr << "rt_6[4] out of bounds: " << rt_6[4] << std::endl; utility_exit_with_message( "RANGE ERROR" ); }
468  if( !( rt_6[ 5 ] >= 0.0 && rt_6[ 5 ] < 360.0 )) { std::cerr << "rt_6[5] out of bounds: " << rt_6[5] << std::endl; utility_exit_with_message( "RANGE ERROR" ); }
469  if( !( rt_6[ 6 ] >= 0.0 && rt_6[ 6 ] <= 180.0 )) { std::cerr << "rt_6[6] out of bounds: " << rt_6[6] << std::endl; utility_exit_with_message( "RANGE ERROR" ); }
470  hash_index( rt_6, cpindex );
471 }
472 
473 void LoopHashMap::hash_index( numeric::geometry::hashing::Real6 transform, core::Size data ){
474  // Hash the transform
475  if( ! hash_->contains( transform ) ){
476  //TR.Error << "OutofBOIUNDS! " << std::endl;
477  return;
478  }
479 
480  boost::uint64_t bin_index = hash_->bin_index( transform );
481  // update previously added leapindex with key
482  loopdb_[data].key = bin_index;
483  // Add Address to map with hashed index
484  backbone_index_map_.insert( std::make_pair( bin_index, data ) );
485 }
486 
487 
488 void LoopHashMap::bbdb_range( std::pair< BackboneIndexMap::iterator, BackboneIndexMap::iterator > & range ){
489  range.first = backbone_index_map_.begin();
490  range.second = backbone_index_map_.end();
491 }
492 
493 // append to a bucket of vectors in the appropriate bin
494 void
495 LoopHashMap::lookup( numeric::geometry::hashing::Real6 transform, std::vector < core::Size > &result )
496 {
497  // Hash the transform
498  if( ! hash_->contains( transform ) ){
499  //TR.Error << "OutofBOIUNDS! " << std::endl;
500  return;
501  }
502 
503  transform[4] = numeric::nonnegative_principal_angle_degrees(transform[4] );
504  transform[5] = numeric::nonnegative_principal_angle_degrees(transform[5] );
505  boost::uint64_t bin_index = hash_->bin_index( transform );
506 
507  // now get an iterator over that map entry
508 
509  std::pair< BackboneIndexMap::iterator,
510  BackboneIndexMap::iterator> range = backbone_index_map_.equal_range( bin_index );
511 
512 
513  for( BackboneIndexMap::iterator it = range.first;
514  it != range.second;
515  ++it)
516  {
517  result.push_back( it->second );
518  }
519 }
520 
521 void LoopHashMap::radial_lookup( core::Size radius, numeric::geometry::hashing::Real6 center, std::vector < core::Size > &result )
522 {
523 
524  center[4] = numeric::nonnegative_principal_angle_degrees(center[4] );
525  center[5] = numeric::nonnegative_principal_angle_degrees(center[5] );
526  std::vector< boost::uint64_t > bin_index_vec = hash_->radial_bin_index( radius, center );
527 
528  for( core::Size i = 0; i < bin_index_vec.size(); ++i ) {
529  // now get an iterator over that map entry
530  std::pair< BackboneIndexMap::iterator,
531  BackboneIndexMap::iterator> range = backbone_index_map_.equal_range( bin_index_vec[i] );
532  for( BackboneIndexMap::iterator it = range.first;
533  it != range.second;
534  ++it)
535  {
536  result.push_back( it->second );
537  }
538  }
539 }
540 
541 Size LoopHashMap::radial_count( core::Size radius, numeric::geometry::hashing::Real6 center ) const
542 {
543  center[4] = numeric::nonnegative_principal_angle_degrees(center[4] );
544  center[5] = numeric::nonnegative_principal_angle_degrees(center[5] );
545  std::vector< boost::uint64_t > bin_index_vec = hash_->radial_bin_index( radius, center );
546  Size count = 0;
547  for( core::Size i = 0; i < bin_index_vec.size(); ++i ) {
548  count += backbone_index_map_.count( bin_index_vec[i] );
549  }
550  return count;
551 }
552 
553 void
554 LoopHashMap::lookup(
555  core::Size index,
556  std::vector < core::Size > &result
557 )
558 {
559  if( index > backbone_index_map_.bucket_count()){
560  //TR.Error << "OutofBOIUNDS! " << std::endl;
561  return;
562  }
563 
564  BackboneIndexMap::local_iterator begin = backbone_index_map_.begin( index );
565  BackboneIndexMap::local_iterator end = backbone_index_map_.end( index );
566 
567  for( BackboneIndexMap::local_iterator it = begin; it != end; ++it) {
568  result.push_back( it->second );
569  }
570 }
571 
572 boost::uint64_t
573 LoopHashMap::return_key( core::Size bb_index )
574 {
575  LeapIndex leap_index = get_peptide( bb_index );
576  return leap_index.key;
577 }
578 
579 void
580 LoopHashMap::radial_lookup_withkey( boost::uint64_t key, core::Size radius, std::vector < core::Size > &result )
581 {
582  // get center of bin from key
583  numeric::geometry::hashing::Real6 center = hash_->bin_center_point( hash_->bin_from_index( key ) );
584  radial_lookup( radius, center, result );
585 }
586 
587 void
588 LoopHashMap::lookup_withkey( boost::uint64_t key, std::vector < core::Size > &result )
589 {
590  std::pair< BackboneIndexMap::iterator,
591  BackboneIndexMap::iterator> range = backbone_index_map_.equal_range( key );
592 
593  for( BackboneIndexMap::iterator it = range.first; it != range.second; ++it) {
594  result.push_back( it->second );
595  }
596  return;
597 }
598 
599 void LoopHashMap::read_legacydb(std::string filename )
600 {
601  // use basic C input - C++ are too memory hungry to deal with these potentially v large files
602  FILE *file = fopen( filename.c_str(), "r" );
603  if( file == NULL ) throw EXCN_DB_IO_Failed( filename, "read" );
604 
605  loopdb_.clear();
606  while( !feof( file ) ){
607  const unsigned int bufsize = 128;
608  LegacyLeapIndex bufferdata[bufsize];
609  size_t readshorts = fread(&bufferdata[0],sizeof(LegacyLeapIndex),bufsize,file);
610  for( unsigned i = 0; i< readshorts; i ++ ){
611  add_legacyleap( bufferdata[i] );
612  }
613  }
614  fclose( file );
615  loopdb_.reserve( loopdb_.size() );
616 
617  TR.Info << "Rehashed dataset:" << backbone_index_map_.size() << " " << loopdb_.size() << std::endl;
618  TR.Info << "Rehashed dataset: OUTOFBOUNDS: " << loopdb_.size() - backbone_index_map_.size() << std::endl;
619 }
620 
621 void LoopHashMap::write_db( std::string filename ){
622  std::ofstream file( filename.c_str() );
623  if( !file ) throw EXCN_DB_IO_Failed( filename, "write" );
624  for( core::Size i = 0; i < loopdb_.size(); i++ ){
625  file << loopdb_[i].index << " " << loopdb_[i].offset << " " << loopdb_[i].key << std::endl;
626  }
627  file.close();
628 }
629 
630 void
631 LoopHashMap::read_db(
632  std::string filename, std::pair< core::Size, core::Size > loopdb_range,
633  std::map< core::Size, bool > & homolog_index
634 ){
635  std::ifstream file( filename.c_str() );
636  if( !file ) throw EXCN_DB_IO_Failed( filename, "read" );
637  std::string line;
638  LeapIndex leap_index;
639  while( getline( file, line ) ) {
640  std::vector<std::string> output;
641  std::string t; std::istringstream sline(line);
642  while(sline >> t){ output.push_back(t); }
643  if( output.size() != 3 ) throw EXCN_Wrong_DB_Format( filename );
644  leap_index.index = boost::lexical_cast< core::Size > ( output[0] );
645  if( leap_index.index < loopdb_range.first ) continue;
646  if( leap_index.index >= loopdb_range.second && loopdb_range.second != 0 ) continue;
647  // Since we're reading in partitions of the bbdb
648  // We also have to offset where the leap_index.index points
649  leap_index.index -= loopdb_range.first;
650  // if the leap_index is in the homolog map, skip it
651  if( homolog_index.find( leap_index.index ) != homolog_index.end() ) continue;
652  leap_index.offset = boost::lexical_cast< core::Size > ( output[1] );
653  leap_index.key = boost::lexical_cast< boost::uint64_t > ( output[2] );
654  add_leap( leap_index, leap_index.key );
655  }
656  TR.Info << "Loophashmap range " << loopdb_[0].index << " " << loopdb_[loopdb_.size() - 1].index << std::endl;
657  file.close();
658 }
659 
660 
661 } // namespace loops
662 } // namespace protocols