Rosetta 3.5
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
compute_sasa.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/packstat/compute_sasa.hh
11 ///
12 /// @brief
13 /// @author will sheffler
14 
15 
16 
17 #include <cmath>
18 #include <basic/database/open.hh>
19 #include <basic/options/option.hh>
20 #include <basic/options/keys/out.OptionKeys.gen.hh>
21 #include <core/io/pdb/pose_io.hh>
22 #include <basic/options/keys/packstat.OptionKeys.gen.hh>
23 #include <core/pose/Pose.hh>
24 #include <core/pose/util.hh>
30 #include <core/types.hh>
31 #include <basic/Tracer.hh>
32 #include <cstdlib>
33 #include <fstream>
34 #include <iostream>
35 #include <numeric/numeric.functions.hh>
36 #include <numeric/NumericTraits.hh>
37 // AUTO-REMOVED #include <numeric/random/random.hh>
38 // AUTO-REMOVED #include <numeric/xyz.io.hh>
39 #include <ObjexxFCL/FArray1D.hh>
40 #include <ObjexxFCL/FArray2D.hh>
41 #include <ObjexxFCL/FArray3D.hh>
42 #include <ObjexxFCL/ubyte.hh>
43 #include <set>
44 #include <sstream>
45 // AUTO-REMOVED #include <time.h>
46 // AUTO-REMOVED #include <utility/basic_sys_util.hh>
47 #include <utility/exit.hh>
48 #include <utility/io/izstream.hh>
49 #include <utility/io/ozstream.hh>
50 
52 #include <utility/vector1.hh>
53 #include <numeric/xyz.functions.hh>
54 #include <numeric/xyzVector.io.hh>
55 #include <numeric/random/random.fwd.hh>
56 #include <ObjexxFCL/format.hh>
57 
58 //Auto Headers
59 #include <core/pose/util.tmpl.hh>
60 //Auto using namespaces
61 namespace ObjexxFCL { } using namespace ObjexxFCL; // AUTO USING NS
62 //Auto using namespaces end
63 
64 //Auto using namespaces
65 namespace ObjexxFCL { namespace fmt { } } using namespace ObjexxFCL::fmt; // AUTO USING NS
66 //Auto using namespaces end
67 
68 
69 
70 namespace core {
71 namespace scoring {
72 namespace packstat {
73 
74 basic::Tracer TRcs("protocols.packstat");
75 
77 typedef std::pair< numeric::xyzMatrix<PackstatReal>, numeric::xyzMatrix<PackstatReal> > RotPair;
78 
79 using utility::vector1;
80 using core::Real;
81 using core::Size;
82 using numeric::xyzVector;
83 
84 namespace old {
85 
86  // this lookup table is used in sasa computation (also in void.cc)
87  short const bit_count[] = { // lookup table for number of 1 bits in a ubyte
88  0,1,1,2,1,2,2,3, 1,2,2,3,2,3,3,4, 1,2,2,3,2,3,3,4, 2,3,3,4,3,4,4,5, // 0x 1x
89  1,2,2,3,2,3,3,4, 2,3,3,4,3,4,4,5, 2,3,3,4,3,4,4,5, 3,4,4,5,4,5,5,6, // 2x 3x
90  1,2,2,3,2,3,3,4, 2,3,3,4,3,4,4,5, 2,3,3,4,3,4,4,5, 3,4,4,5,4,5,5,6, // 4x 5x
91  2,3,3,4,3,4,4,5, 3,4,4,5,4,5,5,6, 3,4,4,5,4,5,5,6, 4,5,5,6,5,6,6,7, // 6x 7x
92  1,2,2,3,2,3,3,4, 2,3,3,4,3,4,4,5, 2,3,3,4,3,4,4,5, 3,4,4,5,4,5,5,6, // 8x 9x
93  2,3,3,4,3,4,4,5, 3,4,4,5,4,5,5,6, 3,4,4,5,4,5,5,6, 4,5,5,6,5,6,6,7, // Ax Bx
94  2,3,3,4,3,4,4,5, 3,4,4,5,4,5,5,6, 3,4,4,5,4,5,5,6, 4,5,5,6,5,6,6,7, // Cx Dx
95  3,4,4,5,4,5,5,6, 4,5,5,6,5,6,6,7, 4,5,5,6,5,6,6,7, 5,6,6,7,6,7,7,8, // Ex Fx
96  };
97 
98  int const nbytes = { 21 };
99  int const nphi = { 64 };
100  int const ntheta = { 64 };
101  int const nolp = { 100 };
102  int const nori = { 162 };
103  int const maskbits = { 162 };
104 
105  FArray2D_int angles( nphi, ntheta );
106  FArray2D_ubyte masks( nbytes, nolp*nori );
107 
108  ///cj Reads in sampling/SASA-angles.dat sampling/SASA-masks.dat
109  void
111  {
112  static bool done_init = false;
113  if( done_init ) return;
114 
115  FArray1D_short tmp( nbytes );
116  static bool init = { false };
117 
118  if ( init ) return;
119  init = true;
120 
121  //cj inputting the masks they are 21 ubytes long, 162x100 (see header)
122  //cj expects file to be complete
123  utility::io::izstream masks_stream( basic::database::full_name("sampling/SASA-masks.dat" ) );
124 
125  for ( int i = 1; i <= nolp*nori; ++i ) {
126  for ( int j = 1; j <= nbytes; ++j ) {
127  masks_stream >> tmp(j);
128  } masks_stream >> skip;
129 
130  for ( int j = 1; j <= nbytes; ++j ) {
131  masks(j,i) = static_cast< ubyte>(tmp(j));
132  }
133  }
134  masks_stream.close();
135 
136  //cj inputting the angle lookup for the mask, need to add a 1 to each number
137  utility::io::izstream angles_stream( basic::database::full_name( "sampling/SASA-angles.dat" ) );
138 
139  //cj 2D array is aphi by theta
140  for ( int i = 1; i <= nphi; ++i ) {
141  for ( int j = 1; j <= ntheta; ++j ) {
142  angles_stream >> angles(i,j);
143  } angles_stream >> skip;
144  //cj for ( j = 1; j <= ntheta; ++j ) {
145  //cj ++angles(i,j);
146  //cj }
147  }
148  angles_stream.close();
149 
150  done_init = true;
151  }
152 
153 
154 } // end namespace old
155 
156 
157 SasaResult::SasaResult(size_t Nprobes, size_t Nspheres) :
158  sphere_sasa( Nspheres, Nprobes, 0.0 )//,
159  // sasa_centers( Nspheres, numeric::xyzVector<PackstatReal>(-12345.0f,-12345.0f,-12345.0f) )
160 {}
161 
163 probe_radii(),
164 prune_max_iters(30),
165 prune_max_delta(5),
166 prune_cavity_burial_probe_radii(),
167 min_hole_radius(0.5),
168 num_cav_ball_layers(0),
169 frac_cav_ball_required_exposed(0.0f),
170 area_cav_ball_required_exposed(0.0f),
171 min_cav_ball_radius(0.5f),
172 num_surrounding_sasa_bins(7),
173 surrounding_sasa_smoothing_window(1),
174 dont_compute_cav_balls( false ),
175 min_cluster_overlap( 0.1 ),
176 cluster_min_volume(10)
177 {
178 }
179 
181  using namespace numeric;
182  using namespace numeric::random;
183  xyzVector<PackstatReal> axis(uniform(),uniform(),uniform());
184  while( axis.length() > 1 ) axis = xyzVector<PackstatReal>(uniform(),uniform(),uniform());
185  PackstatReal mag = uniform() * 2 * numeric::NumericTraits<Real>::pi();
186  return RotPair( rotation_matrix<PackstatReal>( axis, mag ), rotation_matrix<PackstatReal>( axis, -mag ) );
187 }
188 
190  bool operator()( Sphere const & a, Sphere const & b ) {
191  return a.xyz.x() < b.xyz.x();
192  }
193 };
195  bool operator()( Sphere const & a, Sphere const & b ) {
196  return a.id < b.id;
197  }
198 };
200  bool operator()( CavityBall const & a, CavityBall const & b ) {
201  return a.xyz().x() < b.xyz().x();
202  }
203 };
205  bool operator()( CavityBall const & a, CavityBall const & b ) {
206  return (a.radius() - a.exposed_radius) > (b.radius() - b.exposed_radius);
207  }
208 };
210  bool operator()( CavityBall const & a, CavityBall const & b ) {
211  return a.radius() > b.radius();
212  }
213 };
215  bool operator()( CavityBall const & a, CavityBall const & b ) {
216  return ( (a.radius() - ((PackstatReal)a.anb)/50.0) > (b.radius() - ((PackstatReal)b.anb)/50.0 ) );
217  }
218 };
219 
220 
221 PosePackData
222 pose_to_pack_data( Pose const & pose, int include_water ) {
223  using namespace std;
224  using namespace core::io::pdb;
225  ostringstream oss;
226  bool tmp = basic::options::option[basic::options::OptionKeys::out::file::output_virtual]();
227  basic::options::option[basic::options::OptionKeys::out::file::output_virtual].value(true);
228  dump_pdb(pose,oss);
229  basic::options::option[basic::options::OptionKeys::out::file::output_virtual].value(tmp);
230  istringstream iss( oss.str() );
231  AtomRadiusMap arm( include_water );
232  SimplePDB pdb;
233  iss >> pdb;
234  PosePackData p;
235  p.spheres = pdb.get_spheres(arm);
236  p.centers = pdb.get_res_centers();
237  p.labels = pdb.res_labels();
238  return p;
239 }
240 
241 
242 
245  Spheres & spheres,
246  SasaOptions const & opts
247 ) {
248  using namespace old;
249  using namespace utility;
250  using namespace numeric;
251 
252  input_sasa_dats();
253 
254  //SphereIter i = spheres.begin();
255  // PackstatReal prev_x = i->xyz.x();
256  // bool must_sort = false;
257  // for( i = i+1; i != spheres.end(); ++i ) {
258  // if( i->xyz.x() < prev_x ) must_sort = true;
259  // prev_x = i->xyz.x();
260  // }
261  // if( must_sort ) TRcs << "compute_sasa.cc: sorting your spheres ( input arg has changed! )" << std::endl;
262  for( Size i = 1; i <= spheres.size(); ++i ) spheres[i].id = i;
263  /*if( must_sort ) */std::sort( spheres.begin(), spheres.end(), OrderSphereOnX() );
264 
265  SasaResultOP result_op( new SasaResult( opts.probe_radii.size(), spheres.size() ) );
266  SasaResult & result( *result_op );
267  size_t Nspheres = spheres.size();
268  size_t Nprobes = opts.probe_radii.size();
269 
270  int /*in,it, jn,jt,*/ olp, aphi,theta, point,masknum; //,aa,lig_int_count;
271  PackstatReal fraction,total_sa,expose;//,dist_sq,total_sasa5,total_sasa14,
272  PackstatReal const largest_probe( opts.probe_radii[1] ); // first probe is largest
273 
274  ObjexxFCL::FArray3D_ubyte atom_sasa_masks( old::nbytes, Nspheres, Nprobes, NULL );
275 
276  vector1< RotPair > rotations;
277 
278  for ( size_t pr_bin = 1; pr_bin <= Nprobes; ++pr_bin ) {
279  PackstatReal const probe_radius( opts.probe_radii[pr_bin] );
280  //if( pr_bin%10 == 0 ) TRcs << std::sqrt( ((PackstatReal)pr_bin)/((PackstatReal)Nprobes) ) << " ";
281 
282  RotPair rots = rand_rot();
283  rotations.push_back( rots );
284  Rot rot = rots.first;
285  Spheres rspheres;
286  for( SphereCIter i = spheres.begin(); i != spheres.end(); ++i ) {
287  rspheres.push_back( Sphere( rot * i->xyz, i->radius ) );
288  }
289 
290  for( size_t i = 1; i <= Nspheres; ++i ) {
291  // TRcs << ((PackstatReal)i)/((PackstatReal)Nspheres) << std::endl;
292  XYZ const xyz1( rspheres[i].xyz );
293  PackstatReal const rad1( rspheres[i].radius );
294 
295  for( size_t j = 1; j < i; ++j ) {
296  XYZ const xyz2( rspheres[j].xyz );
297  PackstatReal const rad2( rspheres[j].radius );
298 
299  PackstatReal const dist_sq = xyz1.distance_squared(xyz2);
300  PackstatReal const dth = rad1+rad2+2*largest_probe;
301 
302  if ( dist_sq > dth*dth ) continue;
303  if ( dist_sq <= 0.0 ) continue;
304  PackstatReal const dist = std::sqrt(dist_sq);
305 
306  PackstatReal const dth2 = rad1+rad2+2*probe_radius;
307  if ( dist > dth2 ) continue;
308 
309  PackstatReal const irad = rad1 + probe_radius;
310  PackstatReal const jrad = rad2 + probe_radius;
311 
312  // TRcs << i << " " << j << " " << dist_sq << " " << rad1 << " " << rad2 << " " << std::endl;
313 
314  // account for j overlapping i:
315  get_overlap(irad,jrad,dist,olp);
316  get_orientation(xyz1,xyz2,aphi,theta, dist);
317  point = angles(aphi,theta);
318  masknum = point*100+olp;
319  for ( int bb = 1, l = atom_sasa_masks.index(bb,i,pr_bin); bb <= nbytes; ++bb, ++l ) {
320  atom_sasa_masks[ l ] = bit::bit_or( atom_sasa_masks[ l ], masks(bb,masknum) );
321  }
322 
323  // account for i overlapping j:
324  get_overlap(jrad,irad,dist,olp);
325  get_orientation(xyz2,xyz1,aphi,theta, dist);
326  point = angles(aphi,theta);
327  masknum = point*100+olp;
328  for ( int bb = 1, l = atom_sasa_masks.index(bb,j,pr_bin); bb <= nbytes; ++bb, ++l ) {
329  atom_sasa_masks[ l ] = bit::bit_or( atom_sasa_masks[ l ], masks(bb,masknum) );
330  }
331 
332  } // pr_bin
333  } // sphere j
334  } // sphere i
335  // TRcs << std::endl;
336  // TRcs << "SASA work/all " << ((PackstatReal)work) / ((PackstatReal)(clock() - loop)) << std::endl;
337 
338  // compute sasas
339  for( size_t pr_bin = 1; pr_bin <= Nprobes; ++pr_bin ) {
340  for( size_t is = 1; is <= Nspheres; ++is ) {
341  PackstatReal const irad = spheres[is].radius;
342  int ctr = 0;
343  for ( size_t bb = 1, l = atom_sasa_masks.index(bb,is,pr_bin); (int)bb <= nbytes; ++bb, ++l ) {
344  ctr += bit_count[atom_sasa_masks[ l ]];
345  }
346  fraction = static_cast< PackstatReal >( ctr ) / maskbits;
347  total_sa = 12.56637 * ( irad * irad ); // 4*pi*r**2 -- this is M.S.A, not SASA
348  expose = ( 1.0f - fraction ) * total_sa;
349  result.sphere_sasa(spheres[is].id,pr_bin) = expose;
350  } // is
351  } // pr_bin
352 
353  if( opts.dont_compute_cav_balls ) {
354  std::sort( spheres.begin(), spheres.end(), OrderSphereOnID() );
355  return result_op;
356  }
357 
358  ///////////////////////////////////////////////////////////////////////
359  /// compute cavity balls
360  ///////////////////////////////////////////////////////////////////////
361  XYZs const sasa_dots( get_sasa_dot_locations() );
362 
363  size_t ball_count = 0;
364 
365  for ( size_t is = 1; is <= Nspheres; ++is ) {
366  // get largest accessible probe radius for atom ir,ia
367  numeric::xyzVector<PackstatReal> center(0.0f,0.0f,0.0f), median;
368  size_t ii;
369  for ( ii = opts.probe_radii.size(); ii >= 1; ii--) {
370  if ( result.sphere_sasa(is,ii) < 0.0001f ) {
371  break;
372  }
373  }
374  if( ii < 1 || ii == opts.probe_radii.size() ) continue; // not big enough hole
375 
376  size_t const largest_pr_bin = ii+1;
377  PackstatReal const probe_radius = opts.probe_radii[largest_pr_bin];
378  if( probe_radius < opts.min_hole_radius ) {
379  center = -12345.0f;
380  continue; // next sphere
381  }
382 
383  for ( size_t pr_bin = largest_pr_bin;
384  pr_bin <= std::min(largest_pr_bin+opts.num_cav_ball_layers,opts.probe_radii.size());
385  ++pr_bin )
386  {
387  Rot rev_rot = rotations[pr_bin].second;
388  PackstatReal tmp_probe_radius = opts.probe_radii[pr_bin];
389  if( tmp_probe_radius < opts.min_cav_ball_radius ) continue;
390 
391  for ( int bb = 1, l = atom_sasa_masks.index(bb,is,pr_bin); bb <= nbytes; ++bb, ++l ) {
392  ubyte const mask = atom_sasa_masks[ l ]; // atom_sasa_masks_(bb,ia,ir,pr_bin)
393  int NSHORT = 8; if ( bb == 21 ) NSHORT = 2; // 162 dots...
394  for ( short k = 0; k < NSHORT; ++k ) {
395  if ( !( bit::bit_test( static_cast<short>(mask), k ) ) ) {
396  const size_t dot = 8*(bb-1)+k+1;
397 
398  median = (rev_rot * sasa_dots[dot]) * (spheres[is].radius+tmp_probe_radius) + spheres[is].xyz;
399  CavityBall h( ++ball_count, is, median, tmp_probe_radius );
400  result.cavballs.push_back( h );
401 
402  }
403  }
404  } // end bit tests
405  }
406 
407  } // is
408 
409  // std::sort( spheres.begin(), spheres.end(), OrderSphereOnID() );
410  std::sort( result.cavballs.begin(), result.cavballs.end(), OrderCavBallOnX() );
411 
412  return result_op;
413 }
414 
415 void
417  CavBalls & cavballs,
418  SasaOptions const &/*opts*/
419 ) {
420  using namespace ObjexxFCL;
421  using namespace old;
422 
423  FArray2D_ubyte prune_sasa_masks( old::nbytes, cavballs.size(), NULL );
424 
425  std::sort( cavballs.begin(), cavballs.end(), OrderCavBallOnX() ); // already sorted
426 
427  PackstatReal maxrad = 0;
428  for( CavBallIter i = cavballs.begin(); i != cavballs.end(); ++i ) {
429  if( maxrad < i->radius() ) {
430  maxrad = i->radius();
431  }
432  i->area = 0.0f;
433  i->vol = 0.0f;
434  }
435 
436  for( PackstatReal dpr = 0.0f; dpr <= maxrad; dpr += 0.1 ) {
437  PackstatReal dth = 2*(maxrad-dpr);
438  // TRcs << dpr << " ";
439 
440  for( size_t ib = 1; ib <= cavballs.size(); ib++ ) {
441  CavityBall const & cb1( cavballs[ib] );
442  if( cb1.radius() - dpr < 0.1 ) continue;
443 
444  for( size_t jb = ib+1; jb <= cavballs.size(); jb++ ) {
445  CavityBall const & cb2( cavballs[jb] );
446  if( cb2.radius() - dpr < 0.1 ) continue;
447  if( cb2.xyz().x() - cb1.xyz().x() > dth ) break;
448 
449  int olp,aphi,theta,point,masknum;//,aa,lig_int_count;
450  PackstatReal const dis_thresh = (cb1.radius_+cb2.radius_-2*dpr );
451  PackstatReal const dis2 = cb1.xyz().distance_squared( cb2.xyz() );
452  if( dis2 > dis_thresh*dis_thresh || dis2 == 0 ) continue;
453  PackstatReal const dist = sqrt( dis2 );
454 
455  get_overlap( cb1.radius()-dpr, cb2.radius()-dpr , dist, olp );
456  get_orientation( cb1.xyz(), cb2.xyz(), aphi, theta, dist );
457  point = angles(aphi,theta);
458  masknum = point*100+olp;
459  for ( int bb = 1, l = prune_sasa_masks.index(bb,ib); bb <= nbytes; ++bb, ++l ) {
460  prune_sasa_masks[ l ] = bit::bit_or( prune_sasa_masks[ l ], masks(bb,masknum) );
461  }
462  get_overlap( cb2.radius()-dpr, cb1.radius()-dpr, dist, olp );
463  get_orientation( cb2.xyz(), cb1.xyz() , aphi, theta, dist );
464  point = angles(aphi,theta);
465  masknum = point*100+olp;
466  for ( int bb = 1, l = prune_sasa_masks.index(bb,jb); bb <= nbytes; ++bb, ++l ) {
467  prune_sasa_masks[ l ] = bit::bit_or( prune_sasa_masks[ l ], masks(bb,masknum) );
468  }
469 
470  }
471  } // cav ball
472 
473  for( size_t ib = 1; ib <= cavballs.size(); ib++ ) {
474  if( cavballs[ib].radius() - dpr < 0.1 ) continue;
475  int ctr = 0;
476  for ( int bb = 1, l = prune_sasa_masks.index(bb,ib); bb <= nbytes; ++bb, ++l ) {
477  ctr += bit_count[prune_sasa_masks[ l ]];
478  }
480  expose *= 12.56637 * ( cavballs[ib].radius() - dpr ) * ( cavballs[ib].radius() - dpr );
481  cavballs[ib].vol += 0.1 * expose;
482  if( dpr == 0.0 ) {
483  cavballs[ib].area = expose;
484  }
485  }
486 
487  }
488  // TRcs << std::endl;
489 }
490 
491 CavBalls
493  CavBalls & cavballs,
494  SasaOptions const & opts
495 ) {
496  using namespace ObjexxFCL;
497  using namespace old;
498 
499  FArray2D_ubyte prune_sasa_masks( old::nbytes, cavballs.size(), NULL );
500 
501  std::sort( cavballs.begin(), cavballs.end(), OrderCavBallOnX() );
502 
503  PackstatReal maxrad = max_rad( cavballs );
504 
505  for( size_t ib = 1; ib <= cavballs.size(); ib++ ) {
506  CavityBall const & cb1( cavballs[ib] );
507 
508  for( size_t jb = ib+1; jb <= cavballs.size(); jb++ ) {
509  CavityBall const & cb2( cavballs[jb] );
510 
511  if( cb2.xyz().x() - cb1.xyz().x() > maxrad ) break;
512 
513  int olp,aphi,theta,point,masknum;//,aa,lig_int_count;
514  PackstatReal const dis_thresh = (cb1.radius_+cb2.radius_ );
515  PackstatReal const dis2 = cb1.xyz().distance_squared( cb2.xyz() );
516  if( dis2 > dis_thresh*dis_thresh || dis2 == 0 ) continue;
517  PackstatReal const dist = sqrt( dis2 );
518 
519  get_overlap( cb1.radius(), cb2.radius() , dist, olp );
520  get_orientation( cb1.xyz(), cb2.xyz() , aphi, theta, dist );
521  point = angles(aphi,theta);
522  masknum = point*100+olp;
523  for ( int bb = 1, l = prune_sasa_masks.index(bb,ib); bb <= nbytes; ++bb, ++l ) {
524  prune_sasa_masks[ l ] = bit::bit_or( prune_sasa_masks[ l ], masks(bb,masknum) );
525  }
526 
527  get_overlap( cb2.radius(), cb1.radius() , dist, olp );
528  get_orientation( cb2.xyz(), cb1.xyz() , aphi, theta, dist );
529  point = angles(aphi,theta);
530  masknum = point*100+olp;
531  for ( int bb = 1, l = prune_sasa_masks.index(bb,jb); bb <= nbytes; ++bb, ++l ) {
532  prune_sasa_masks[ l ] = bit::bit_or( prune_sasa_masks[ l ], masks(bb,masknum) );
533  }
534 
535  }
536  } // cav ball
537 
538  // make new list with only buried cav balls
539  vector1< CavityBall > not_hidden_cav_balls;
540 
541  for( size_t ii = 1; ii <= cavballs.size(); ii++ ) {
542  int ctr = 0;
543  for ( int bb = 1, l = prune_sasa_masks.index(bb,ii); bb <= nbytes; ++bb, ++l ) {
544  ctr += bit_count[prune_sasa_masks[ l ]];
545  }
547  expose *= 12.56637 * cavballs[ii].radius() * cavballs[ii].radius();
549  if( (PackstatReal)ctr < dot_th && expose > opts.area_cav_ball_required_exposed ) {
550  not_hidden_cav_balls.push_back( cavballs[ii] );
551  }
552  }
553  //TRcs << "pruned " << cavballs.size() - not_hidden_cav_balls.size() << " hidden balls" << std::endl;
554  return not_hidden_cav_balls;
555 }
556 
557 size_t
559  Spheres & spheres,
560  CavBalls & cavballs,
561  PackstatReal pr
562 ) {
563  using namespace ObjexxFCL;
564  using namespace old;
565 
566  FArray2D_ubyte prune_sasa_masks( old::nbytes, cavballs.size(), 0 );
567 
568  PackstatReal const max_cbrad = max_rad( cavballs );
569  PackstatReal const max_dis_sphere = max_rad( spheres ) + max_cbrad + 2*pr;
570  PackstatReal const max_dis_cavball = 2*max_cbrad+2*pr;
571 
572  for( size_t ib = 1; ib <= cavballs.size(); ib++ ) {
573  CavityBall const & cb( cavballs[ib] );
574  if( cb.exposed_radius >= pr ) continue;
575 
576  size_t begin = search_x( spheres, cb.xyz().x()-max_dis_sphere );
577  for( size_t js = begin; js <= spheres.size(); ++js ) {
578  Sphere const & s( spheres[js] );
579  if( s.xyz.x() - cb.xyz().x() > max_dis_sphere ) break;
580 
581  int olp,aphi,theta,point,masknum;//,aa,lig_int_count;
582  PackstatReal const dis_thresh = (cb.radius_+s.radius+2*pr );
583  PackstatReal const dis2 = cb.xyz().distance_squared( s.xyz );
584  if( dis2 > dis_thresh*dis_thresh ) continue;
585  PackstatReal const dist = sqrt( dis2 );
586 
587  get_overlap( cb.radius()+pr, s.radius+pr , dist, olp );
588  get_orientation( cb.xyz(), s.xyz , aphi, theta, dist );
589  point = angles(aphi,theta);
590  masknum = point*100+olp;
591  for ( int bb = 1, l = prune_sasa_masks.index(bb,ib); bb <= nbytes; ++bb, ++l ) {
592  prune_sasa_masks[ l ] = bit::bit_or( prune_sasa_masks[ l ], masks(bb,masknum) );
593  }
594  } // sphere
595 
596  for( size_t jb = ib+1; jb < cavballs.size(); jb++ ) {
597  CavityBall const & cb2( cavballs[jb] );
598  if( cb2.xyz().x() - cb.xyz().x() > max_dis_cavball ) break;
599  if( cb2.exposed_radius >= pr ) continue;
600 
601  int olp,aphi,theta,point,masknum;//,aa,lig_int_count;
602  PackstatReal const dis_thresh = (cb.radius_+cb2.radius_+2*pr );
603  PackstatReal const dis2 = cb.xyz().distance_squared( cb2.xyz() );
604  if( dis2 > dis_thresh*dis_thresh || dis2 == 0 ) continue;
605  PackstatReal const dist = sqrt( dis2 );
606 
607  get_overlap( cb.radius()+pr, cb2.radius_+pr , dist, olp );
608  get_orientation( cb.xyz(), cb2.xyz() , aphi, theta, dist );
609  point = angles(aphi,theta);
610  masknum = point*100+olp;
611  for ( int bb = 1, l = prune_sasa_masks.index(bb,ib); bb <= nbytes; ++bb, ++l ) {
612  prune_sasa_masks[ l ] = bit::bit_or( prune_sasa_masks[ l ], masks(bb,masknum) );
613  }
614 
615  }
616 
617  } // cav ball
618 
619  // make new list with only buried cav balls
620  size_t num_exposed = 0;
621  vector1< CavityBall > buried_cav_balls;
622  for( size_t ii = 1; ii <= cavballs.size(); ii++ ) {
623  if( cavballs[ii].exposed_radius >= pr ) {
624  ++num_exposed;
625  continue;
626  }
627  int ctr = 0;
628  for ( int bb = 1, l = prune_sasa_masks.index(bb,ii); bb <= nbytes; ++bb, ++l ) {
629  ctr += bit_count[prune_sasa_masks[ l ]];
630  }
631  if( ctr != old::maskbits ) { // not buried
632  cavballs[ii].exposed_radius = pr;
633  ++num_exposed;
634  }
635  }
636  return num_exposed;
637 }
638 
639 CavBalls
641  Spheres & spheres,
642  CavBalls & cavballs,
643  SasaOptions const & opts
644 ) {
645  using namespace std;
646  //TRcs << "about to prune cavity balls" << std::endl;
647  assert( opts.prune_cavity_burial_probe_radii.size() >= 1 );
648 
649  PackstatReal largest_probe_radius = opts.prune_cavity_burial_probe_radii[1];
650  size_t delta_th = opts.prune_max_delta;
651  int iter_th = opts.prune_max_iters;
652 
653  {
654  TRcs << "prune raduis " << largest_probe_radius << " ";
655  int num_prune_steps(0);
656  size_t last_num = 0;
657  size_t num_exposed;
658  while( true ) {
659  num_exposed = prune_1pass( spheres, cavballs, largest_probe_radius );
660  ++num_prune_steps;
661  TRcs << cavballs.size() - num_exposed << " ";
662  if ( num_prune_steps >= iter_th || (num_exposed-last_num) <= delta_th ) break;
663  last_num = num_exposed;
664  }
665  TRcs << std::endl;
666  }
667 
668  // make new list with exposed removed
669  CavBalls buried_cav_balls;
670  int id = 0;
671  for( CavBallIter i = cavballs.begin(); i != cavballs.end(); ++i ) {
672  if( i->exposed_radius < largest_probe_radius ) {
673  buried_cav_balls.push_back( *i );
674  buried_cav_balls[ buried_cav_balls.size() ].id_ = ++id;
675  }
676  }
677 
678  // mark balls for rest of radii
679  for( size_t i = 2; i <= opts.prune_cavity_burial_probe_radii.size(); ++i ) {
681  TRcs << "prune raduis " << pr << " ";
682  int num_prune_steps(0);
683  size_t last_num = 0;
684  size_t num_exposed;
685  while( true ) {
686  num_exposed = prune_1pass( spheres, buried_cav_balls, pr );
687  ++num_prune_steps;
688  TRcs << buried_cav_balls.size() - num_exposed << " ";
689  if ( num_prune_steps >= iter_th || (num_exposed-last_num) <= delta_th ) break;
690  last_num = num_exposed;
691  }
692  TRcs << std::endl;
693  }
694 
695  return buried_cav_balls;
696 }
697 
698 void
700  Spheres & spheres,
701  CavBalls & cavballs,
702  PackstatReal dis
703 ) {
704  PackstatReal dis2 = dis*dis;
705  for( CavBallIter c = cavballs.begin(); c != cavballs.end(); ++c ) {
706  c->anb = 0;
707  for( SphereIter s = spheres.begin(); s != spheres.end(); ++s ) {
708  if( s->xyz.distance_squared( c->xyz() ) <= dis2 ) {
709  c->anb++;
710  }
711  }
712  }
713 }
714 
716  CavBalls cavballs,
717  PackstatReal spacing
718 ) {
719  std::sort( cavballs.begin(), cavballs.end(), OrderCavBallOnR() );
720  CavBalls selected_cavballs;
721  PackstatReal const dist_th = spacing*spacing;
722  for( CavBallIter i = cavballs.begin(); i != cavballs.end(); ++i ) {
723  bool ok_to_add = true;
724  for( CavBallIter j = selected_cavballs.begin(); j != selected_cavballs.end(); ++j ) {
725  if( i->xyz().distance_squared(j->xyz()) < dist_th ) ok_to_add = false;
726  }
727  if( ok_to_add ) selected_cavballs.push_back( *i );
728  }
729  return selected_cavballs;
730 }
731 
732 
733 Real overlap(CavityBall const & cb1, CavityBall const & cb2) {
734  core::Real const d2 = cb1.xyz().distance_squared(cb2.xyz());
735  if( d2 > 36.0 ) return 0.0;
736  core::Real const d = std::sqrt(d2);
737  // return cb1.radius() + cb2.radius() - d;
738  core::Real r1 = cb1.radius();
739  core::Real r2 = cb2.radius();
740  if( d > r1+r2 ) return 0.0;
741  core::Real alpha = r2*sin( acos( (d*d + r2*r2 - r1*r1) / ( 2*d*r2 ) ) );
742  // std::cerr << r1 << " " << r2 << " " << d << " " << alpha << std::endl;
743  return alpha*alpha*numeric::NumericTraits<Real>::pi();
744 }
745 
747 compute_cav_ball_clusters( CavBalls & cavballs, SasaOptions const & opts ) {
748  using namespace numeric;
749 
750  for( Size i = 1; i <= cavballs.size(); i++ ) {
751  cavballs[i].cluster_ = i;
752  }
753 
754  for( Size i = 1; i <= cavballs.size(); i++ ) {
755  CavityBall & cb1( cavballs[i] );
756  // assume that cb1 has the right cluster before each 2nd loop
757  for( Size j = i+1; j <= cavballs.size(); j++ ) {
758  CavityBall & cb2( cavballs[j] );
759  if( abs( cb1.xyz().x() - cb2.xyz().x() ) > 6.0 ) continue;
760  // core::Real d = cb1.xyz().distance(cb2.xyz());
761  if( overlap(cb1,cb2) >= opts.min_cluster_overlap ) {
762  int c = numeric::min(cb1.cluster_,cb2.cluster_);
763  cb1.cluster_ = c;
764  cb2.cluster_ = c;
765  }
766  }
767  }
768 
769  while(true) {
770  bool fail = false;
771  for( Size i = 1; i <= cavballs.size(); i++ ) {
772  CavityBall & cb1( cavballs[i] );
773  for( Size j = i+1; j <= cavballs.size(); j++ ) {
774  CavityBall & cb2( cavballs[j] );
775  if( abs( cb1.xyz().x() - cb2.xyz().x() ) > 6.0 ) continue;
776  // core::Real d = cb1.xyz().distance(cb2.xyz());
777  if( cb2.cluster_ != cb1.cluster_ && overlap(cb1,cb2) >= opts.min_cluster_overlap ) {
778  fail = true;
779  int from = numeric::max(cb1.cluster_,cb2.cluster_);
780  int to = numeric::min(cb1.cluster_,cb2.cluster_);
781  for( Size k = 1; k <= cavballs.size(); k++ ) {
782  if(cavballs[k].cluster_==from) cavballs[k].cluster_ = to;
783  }
784  }
785  if(fail) break;
786  }
787  if(fail) break;
788  }
789  if(!fail) break;
790  }
791 
792  // now renumber the clusters starting from 1
793  std::map<Size,Size> perm;
794  Size count = 1;
795  for( Size i = 1; i <= cavballs.size(); i++ ) {
796  if( perm.find(cavballs[i].cluster_) == perm.end() ) {
797  perm[cavballs[i].cluster_] = count;
798  count++;
799  }
800  }
801  for( Size i = 1; i <= cavballs.size(); i++ ) {
802  cavballs[i].cluster_ = perm[cavballs[i].cluster_];
803  }
804 
805  vector1< xyzVector<core::Real> > cluster_centers;
806  vector1< core::Real > cluster_volume;
807  vector1< core::Real > cluster_surf;
808  vector1< core::Real > cluster_counts;
809  vector1< core::Real > cluster_surface_accessibility;
810  for( Size i = 1; i <= cavballs.size(); i++ ) {
811  CavityBall const & cb( cavballs[i] );
812  if( (Size)cb.cluster_ > cluster_centers.size() ) {
813  cluster_centers.resize(cb.cluster_);
814  cluster_volume .resize(cb.cluster_);
815  cluster_surf .resize(cb.cluster_);
816  cluster_counts .resize(cb.cluster_);
817  cluster_surface_accessibility.resize(cb.cluster_);
818  }
819  }
820 
821  for( Size i = 1; i <= cluster_centers.size(); i++ ) {
822  cluster_centers[i] = numeric::xyzVector<core::Real>(0.0,0.0,0.0);
823  cluster_volume[i] = 0.0;
824  cluster_counts[i] = 0.0;
825  cluster_surf [i] = 0.0;
826  cluster_surface_accessibility[i] = 0.0;
827  }
828 
829  for( Size i = 1; i <= cavballs.size(); i++ ) {
830  CavityBall const & cb( cavballs[i] );
831  if( (Size)cb.cluster_ > cluster_centers.size() ) {
832  cluster_centers.resize(cb.cluster_);
833  cluster_volume .resize(cb.cluster_);
834  cluster_surf .resize(cb.cluster_);
835  cluster_counts .resize(cb.cluster_);
836  }
837  cluster_centers[cb.cluster_] += cb.xyz();
838  cluster_surf [cb.cluster_] += cb.area;
839  cluster_volume [cb.cluster_] += cb.vol;
840  cluster_counts [cb.cluster_] += 1.0;
841  cluster_surface_accessibility[cb.cluster_] = numeric::max(cb.exposed_radius,cluster_surface_accessibility[cb.cluster_]);
842  // std::cerr << cb.xyz().z() << " " << cluster_centers[cb.cluster_].z() << std::endl;
843  }
844  for( Size i = 1; i <= cluster_counts.size(); i++ ) {
845  cluster_centers[i] /= cluster_counts[i];
846  // std::cerr << cluster_counts[i] << " " << cluster_centers[i] << std::endl;
847  }
848 
850  for( Size i = 1; i <= cluster_counts.size(); i++ ) {
851  // TRcs << "Cavity: " << i
852  // << " volume " << cluster_volume[i]
853  // << " surf " << cluster_surf[i]
854  // << " Nballs " << cluster_counts[i]
855  // << " center " << cluster_centers[i].x()
856  // << ", " << cluster_centers[i].y()
857  // << ", " << cluster_centers[i].z()
858  // << std::endl;
859  if( cluster_volume[i] > opts.cluster_min_volume ) {
860  CavityBallCluster cbc;
861  cbc.volume = cluster_volume[i];
862  cbc.surface_area = cluster_surf[i];
863  cbc.center = cluster_centers[i];
864  cbc.surface_accessibility = cluster_surface_accessibility[i];
865  for( Size j = 1; j <= cavballs.size(); j++ ) {
866  CavityBall const & cb( cavballs[j] );
867  if( cb.cluster_ == (int)i ) {
868  // std::cout << "cluster " << i << " add cav ball" << std::endl;
869  cbc.cavballs.push_back(cb);
870  }
871  }
872  result.push_back( cbc );
873  }
874  }
875 
876  std::sort( result.begin(), result.end(), OrderCBC() );
877 
878  for( Size i = 1; i <= result.size(); i++ ) {
879  for( Size j = 1; j <= result[i].cavballs.size(); j++ ) {
880  result[i].cavballs[j].cluster_ = i;
881  }
882  }
883 
884  return result;
885 }
886 
889  XYZ const & xyz,
890  Spheres & spheres, // assumes spheres is sorted on x!
891  SasaResultOP result,
892  SasaOptions const & opts
893 ) {
894  using namespace utility;
895  using namespace numeric;
896 
897 
898  // PackstatReal dist_th = (PackstatReal)opts.num_surrounding_sasa_bins;
899  size_t Nprobes = opts.probe_radii.size() / opts.surrounding_sasa_smoothing_window;
900  FArray2D<PackstatReal> tot_sasa( Nprobes, opts.num_surrounding_sasa_bins, 0.0f );
901  size_t begin = 1;//search_x( spheres, xyz.x() - dist_th );
902  // TRcs << "begin " << begin << std::endl;
903  for( size_t is = begin; is <= spheres.size(); ++is ) {
904  Sphere const & sphere( spheres[is] );
905  //if( sphere.xyz.x() > xyz.x() + dist_th ) break;
906  PackstatReal dist = xyz.distance( sphere.xyz );
907  for( size_t id = 1; id <= opts.num_surrounding_sasa_bins; ++id ) {
908  if( dist <= (PackstatReal)id ) {
909  for( size_t pr = 1; pr <= Nprobes; ++pr ) {
910  for( size_t io = 1; io <= opts.surrounding_sasa_smoothing_window; ++io ) {
911  // std::cerr << "SASA " << is << " " << id << " " << pr << " " << result->sphere_sasa(is,pr) << std::endl;
912  size_t sspr = (pr-1)*opts.surrounding_sasa_smoothing_window+io;
913  // std::cerr << "pr " << pr << " sspr " << sspr << std::endl;
914  tot_sasa(pr,id) += result->sphere_sasa(is,sspr);
915  }
916  }
917  break;
918  }
919  }
920  }
921  if( opts.surrounding_sasa_smoothing_window > 1 ) {
922  for( size_t id = 1; id <= opts.num_surrounding_sasa_bins; ++id ) {
923  for( size_t pr = 1; pr <= Nprobes; ++pr ) {
924  tot_sasa(pr,id) /= opts.surrounding_sasa_smoothing_window;
925  }
926  }
927  }
929  for( size_t id = 1; id <= opts.num_surrounding_sasa_bins; ++id ) {
930  for( size_t pr = 2; pr <= Nprobes; ++pr ) {
931  psrdOP->msa(id,pr-1) = tot_sasa(pr,id) - tot_sasa(1,id); // stupid reverse indicies...
932  // std::cout << psrdOP->msa(id,pr-1) << " ";
933  }
934  }
935  // std::cout << std::endl;
936  // std::exit(-1);
937  return psrdOP;
938 }
939 
942  PosePackData & pd,
943  core::Size oversample
944 ) {
945 
946  assert( pd.spheres.size() > 0 );
947  assert( pd.centers.size() > 0 );
948 
949  SasaOptions opts;
950  opts.prune_max_iters = 0;
951  opts.prune_max_delta = 0;
952  opts.num_cav_ball_layers = 0;
953  opts.frac_cav_ball_required_exposed = 0.00;
954  opts.area_cav_ball_required_exposed = 0.00;
955  opts.surrounding_sasa_smoothing_window = 1+2*oversample;
956  opts.num_surrounding_sasa_bins = 7;
957  for( core::Size ipr = 1; ipr <= 31; ++ipr ) {
958  PackstatReal pr = 3.0 - ((double)(ipr-1))/10.0;
959  PackstatReal ostep = 0.1 / (oversample*2.0+1.0);
960  for( core::Size i = 1; i <= oversample; ++i ) opts.probe_radii.push_back( pr + i*ostep );
961  opts.probe_radii.push_back( pr );
962  for( core::Size i = 1; i <= oversample; ++i ) opts.probe_radii.push_back( pr - i*ostep );
963  }
964  // for( core::Size i = 1; i <= opts.probe_radii.size(); ++i )
965  // std::cerr << "PR " << i << " " << opts.probe_radii[i] << std::endl;
966  // opts.prune_cavity_burial_probe_radii.push_back( 1.6 );
967 
968  SasaResultOP result = compute_sasa( pd.spheres, opts );
969  //std::cerr << "compute_sasa: num cav balls: " << result->cavballs.size() << std::endl;
971  for( core::Size i = 1; i <= pd.centers.size(); ++i ) {
972  // std::cout << i << " ";
973  psrds.push_back( compute_surrounding_sasa( pd.centers[i], pd.spheres, result, opts ) );
974  }
975  // std::exit(-1);
976  PackingScore /*ps_respred(7,30,false),*/ ps_discrim(7,30,true);
977  init_packing_score_discrim( ps_discrim );
978  // init_packing_score_respred( ps_respred );
979 
980  // std::pair<core::Real,core::Real> score;
981  // std::cerr << "DISCRIM" << std::endl;
982  return ps_discrim.score( psrds );
983  // std::cerr << "RESPRED" << std::endl;
984  // score.second = ps_respred.score( psrds );
985 
986  // return score;
987 
988 }
989 
992  PosePackData & pd, core::Size oversample
993 ) {
994  return compute_atom_packing_scores( pd, oversample );
995 }
996 
999  PosePackData & pd,
1000  core::Size oversample
1001 ) {
1002  assert( pd.spheres.size() > 0 );
1003  assert( pd.centers.size() > 0 );
1004 
1005  SasaOptions opts;
1006  opts.prune_max_iters = 0;
1007  opts.prune_max_delta = 0;
1008  opts.num_cav_ball_layers = 0;
1009  opts.frac_cav_ball_required_exposed = 0.00;
1010  opts.area_cav_ball_required_exposed = 0.00;
1011  opts.surrounding_sasa_smoothing_window = 1+2*oversample;
1012  opts.num_surrounding_sasa_bins = 7;
1013  for( core::Size ipr = 1; ipr <= 31; ++ipr ) {
1014  PackstatReal pr = 3.0 - ((double)(ipr-1))/10.0;
1015  PackstatReal ostep = 0.1 / (oversample*2.0+1.0);
1016  for( core::Size i = 1; i <= oversample; ++i ) opts.probe_radii.push_back( pr + i*ostep );
1017  opts.probe_radii.push_back( pr );
1018  for( core::Size i = 1; i <= oversample; ++i ) opts.probe_radii.push_back( pr - i*ostep );
1019  }
1020 
1021  PackingScore ps_discrim(7,30,true);
1022  init_packing_score_discrim( ps_discrim );
1023  vector1<Real> res_scores;
1024  SasaResultOP result = compute_sasa( pd.spheres, opts );
1025  for( core::Size i = 1; i <= pd.centers.size(); ++i ) {
1026  PackingScoreResDataCOP ss = compute_surrounding_sasa( pd.centers[i], pd.spheres, result, opts );
1027  res_scores.push_back( ps_discrim.score( ss ) );
1028  }
1029 
1030  return res_scores;
1031 }
1032 
1033 core::Real
1035  Pose const & pose,
1036  core::Size oversample
1037 ) {
1038  PosePackData pd( pose_to_pack_data(pose) );
1039  return compute_packing_score( pd, oversample );
1040 }
1041 
1042 
1045  Pose const & pose,
1046  core::Size oversample
1047 ) {
1048  PosePackData pd( pose_to_pack_data(pose) );
1049  return compute_residue_packing_scores( pd, oversample );
1050 }
1051 
1052 core::Real
1054  Pose const & pose,
1055  int const seqpos,
1056  core::Size oversample
1057 ) {
1058  PosePackData pd( pose_to_pack_data(pose) );
1059  return compute_residue_packing_score( pd, seqpos, oversample );
1060 }
1061 
1062 
1063 core::Real
1065  PosePackData & pd,
1066  int const seqpos,
1067  core::Size oversample
1068 ) {
1069  assert( pd.spheres.size() > 0 );
1070  assert( pd.centers.size() > 0 );
1071 
1072  SasaOptions opts;
1073  opts.prune_max_iters = 0;
1074  opts.prune_max_delta = 0;
1075  opts.num_cav_ball_layers = 0;
1076  opts.frac_cav_ball_required_exposed = 0.00;
1077  opts.area_cav_ball_required_exposed = 0.00;
1078  opts.surrounding_sasa_smoothing_window = 1+2*oversample;
1079  opts.num_surrounding_sasa_bins = 7;
1080  for( core::Size ipr = 1; ipr <= 31; ++ipr ) {
1081  PackstatReal pr = 3.0 - ((double)(ipr-1))/10.0;
1082  PackstatReal ostep = 0.1 / (oversample*2.0+1.0);
1083  for( core::Size i = 1; i <= oversample; ++i ) opts.probe_radii.push_back( pr + i*ostep );
1084  opts.probe_radii.push_back( pr );
1085  for( core::Size i = 1; i <= oversample; ++i ) opts.probe_radii.push_back( pr - i*ostep );
1086  }
1087 
1088  PackingScore ps_discrim(7,30,true);
1089  init_packing_score_discrim( ps_discrim );
1090 
1091  SasaResultOP result = compute_sasa( pd.spheres, opts );
1092 
1093  PackingScoreResDataCOP ss = compute_surrounding_sasa( pd.centers[seqpos], pd.spheres, result, opts );
1094 
1095  for( int i = 1; i <= (int)ss->nrad(); ++i ) {
1096  for( int j = 1; j <= (int)ss->npr() ; ++j ) {
1097  std::cout << ss->msa(i,j) << " ";
1098  }
1099  }
1100 
1101  return ps_discrim.score( ss );
1102 }
1103 
1106  Pose const & pose,
1107  core::Size oversample
1108 ) {
1109  core::id::AtomID_Map<core::Real> atom_scores(0.0);
1110  core::pose::initialize_atomid_map( atom_scores, pose, 0.0 );
1111  PosePackData pd( pose_to_pack_data(pose) );
1112  vector1<Real> res_scores = compute_atom_packing_scores( pd, oversample );
1113  assert( res_scores.size() == pose.total_residue() );
1114  for( core::Size ir = 1; ir <= pose.total_residue(); ++ir ) {
1115  // numeric::xyzVector<Real> center(0,0,0);
1116  for( core::Size ia = 1; ia <= pose.residue(ir).nheavyatoms(); ++ia ) {
1117  // center += pose.residue(ir).xyz(ia);
1118  atom_scores[ core::id::AtomID(ia,ir) ] = res_scores[ir];
1119  // std::cerr << "RES SCORES " << ir << " " << ia << " " << res_scores[ir] << std::endl;
1120  }
1121  // center /= pose.residue(ir).nheavyatoms();
1122  }
1123  return atom_scores;
1124 }
1125 
1127  Real w = exp( -pow(d-d0,2.0)/10.0 ) + exp(-d/10.0) - 1.5/(d+1.0);
1128  if( w < 0 ) w = 0.0;
1129  return w;
1130 }
1131 
1132 
1135  core::pose::Pose & pose,
1137  core::pose::PoseOP native
1138 ) {
1139 
1140  using namespace numeric;
1141 
1142  PosePackData pd = pose_to_pack_data(pose);
1143 
1144  Spheres & spheres(pd.spheres);
1145  // vector1< xyzVector<PackstatReal> > & centers( pd.centers );
1146 
1147  SasaOptions opts;
1148  opts.prune_max_iters = 999;
1149  opts.prune_max_delta = 0;
1150  opts.num_cav_ball_layers = 10;
1151  opts.frac_cav_ball_required_exposed = 0.00;
1152  opts.area_cav_ball_required_exposed = 0.00;
1153  opts.surrounding_sasa_smoothing_window = 3;
1154  opts.min_cav_ball_radius = 0.7;
1155  opts.min_cluster_overlap = 0.1; //how much overlap before considered to be in the same cluster
1156  opts.cluster_min_volume = 10.0;
1157  for( PackstatReal pr = 3.0; pr >= 0.4; pr -= 0.1 ) opts.probe_radii.push_back(pr);
1158  opts.prune_cavity_burial_probe_radii.push_back( 1.6 );
1159  // if( surface_accessibility ) {
1160  // for( PackstatReal pr = burial_radius-0.1; pr >= 0.1; pr -= 0.1 ) {
1161  // opts.prune_cavity_burial_probe_radii.push_back(pr);
1162  // }
1163  // }
1164 
1165  //TRcs << "compute MSAs" << std::endl;
1166  SasaResultOP sr = compute_sasa( spheres, opts );
1167 
1168  ////////////////////////////////////////////////////////////////////////////////////////////////
1169  CavBalls cavballs = sr->cavballs;
1170  //TRps << "pruning hidden cav balls " << cavballs.size() << std::endl;
1171  cavballs = prune_hidden_cavity_balls( cavballs, opts );
1172 
1173  //TRps << "pruning exposed cav balls " << cavballs.size() << std::endl;
1174  cavballs = prune_cavity_balls( spheres, cavballs, opts );
1175 
1176  //TRps << "compute cav ball volumes " << cavballs.size() << std::endl;
1177  compute_cav_ball_volumes( cavballs, opts );
1178  compute_cav_ball_neighbor_count( spheres, cavballs, 10.0 );
1179 
1180  vector1< CavityBallCluster > clusters =
1181  compute_cav_ball_clusters( cavballs, opts );
1182  assert(clusters.size() > 0);
1183 
1184  vector1< std::map<id::AtomID,Real> > constraints_list;
1185 
1186  for( Size roi_i = 1; roi_i <= rois.size(); ++roi_i ) {
1187  Size roi = rois[roi_i];
1188 
1189  if( pose.residue(roi).nheavyatoms() <= 4 ) {
1190  utility_exit_with_message("residue of interest must have a CB!");
1191  }
1192  numeric::xyzVector<core::Real> roi_ca( pose.residue(roi).xyz(2) );
1193  core::Real dist_max = 0;
1195  numeric::xyzVector<core::Real> native_roi_max;
1196  for( Size ia = 5; ia <= pose.residue(roi).nheavyatoms(); ++ia ) {
1197  if( roi_ca.distance(pose.residue(roi).xyz(ia)) > dist_max ) {
1198  roi_max = pose.residue(roi).xyz(ia);
1199  if( native ) native_roi_max = native->residue(roi).xyz(ia);
1200  dist_max = roi_max.distance(roi_ca);
1201  }
1202  }
1203  Real const d0 = roi_max.distance(roi_ca);
1204  TRcs << "PACKSTAT_ROI " << roi << " d0 is " << d0 << std::endl;
1205  Real best_clust_score = 0.0;
1206  //Size best_clust = 123456789;
1207  numeric::xyzVector<core::Real> best_clust_wcen;
1208  for( Size i = 1; i <= clusters.size(); ++i ) {
1209  Real clust_score = 0.0, clust_wtot = 0.0;
1210  numeric::xyzVector<core::Real> clust_wcen(0,0,0);
1211  for( Size j = 1; j <= clusters[i].cavballs.size(); ++j ) {
1212  numeric::xyzVector<core::Real> xyz( clusters[i].cavballs[j].xyz() );
1213  Real const d = roi_ca.distance(xyz);
1214  Real const w = weight_func(d0,d);
1215  clust_score+= w*clusters[i].cavballs[j].vol*(clusters[i].cavballs[j].anb-50);
1216  clust_wtot += w*clusters[i].cavballs[j].vol*(clusters[i].cavballs[j].anb-50);
1217  clust_wcen += w*clusters[i].cavballs[j].vol*(clusters[i].cavballs[j].anb-50)*clusters[i].cavballs[j].xyz();
1218  }
1219  if( clust_score <= 0 ) continue;
1220  clust_wcen /= clust_wtot;
1221 
1222  TRcs << "PACKSTAT_ROI_CLUSTER " << roi << " clust " << i << " vol " << clusters[i].volume << " score " << clust_score;
1223  if( native ) {
1224  Real dnat = clust_wcen.distance(native_roi_max);
1225  TRcs << " dnat " << dnat;
1226  }
1227  TRcs << std::endl;
1228 
1229  if( clust_score > best_clust_score ) {
1230  best_clust_score = clust_score;
1231  best_clust_wcen = clust_wcen;
1232  //best_clust = i; // set but never used ~Labonte
1233  }
1234  }
1235 
1236  std::set<id::AtomID> nbrs;
1237  for( Size ir = 1; ir <= pose.n_residue(); ++ir ) {
1238  for( Size ia = 1; ia <= pose.residue(ir).nheavyatoms(); ++ia ) {
1239  id::AtomID const aid(ia,ir);
1240  if( best_clust_wcen.distance_squared(pose.xyz(aid)) > 49.0 ) continue;
1241  // possibly some effort to pick only atoms lining cluster?
1242  nbrs.insert(aid);
1243  }
1244  }
1245 
1246  TRcs << "PACKSTAT_ROI " << roi << " cluster weighted center " << best_clust_wcen << std::endl;
1247 
1248  std::map<id::AtomID,Real> constraints;
1249 
1250  for( std::set<id::AtomID>::iterator i = nbrs.begin(); i != nbrs.end(); ++i ) {
1251  id::AtomID aid( *i );
1252  constraints[aid] = best_clust_wcen.distance(pose.xyz(aid));
1253  TRcs << "PACKSTAT_ROI " << roi << " constraint: " << aid << " " << " " << std::endl;
1254  }
1255 
1256  constraints_list.push_back(constraints);
1257 
1258  /////////////////////////////// test output ///////////////////////////////////////////////////
1259  utility::io::ozstream out( ("PACKSTAT_ROI_"+string_of(roi)+".pdb").c_str() );
1260 
1261  pose.dump_pdb(out);
1262 
1263  for( Size i = 1; i <= clusters.size(); i++ ) {
1264  if( clusters[i].volume < 10 ) continue;
1265  for( Size j = 1; j <= clusters[i].cavballs.size(); j++ ) {
1266  out << clusters[i].cavballs[j].hetero_atom_line(i,i) << std::endl;
1267  }
1268  }
1269 
1270  out << "HETATM" + I( 5, 0 ) + " C CEN X"
1271  + I( 4, 0 ) + " "
1272  + F( 8, 3, best_clust_wcen.x() ) + F( 8, 3, best_clust_wcen.y() ) + F( 8, 3, best_clust_wcen.z() )
1273  + F( 6, 2, 0.0 ) + ' ' + F( 5, 2,2.0);
1274 
1275 
1276  out.close();
1277 
1278  }
1279 
1280  return constraints_list;
1281 }
1282 
1283 
1284 
1285 void output_packstat_pdb( core::pose::Pose & pose, std::ostream & out ) {
1286  using namespace core::scoring::packstat;
1287  using namespace std;
1288  using namespace core;
1289  using namespace basic::options;
1290  using namespace ObjexxFCL::fmt;
1291  using namespace numeric;
1292  using namespace utility;
1293 
1294  bool surface_accessibility = option[ OptionKeys::packstat::surface_accessibility ]();
1295  core::Real burial_radius = option[ OptionKeys::packstat::cavity_burial_probe_radius ]();
1296 
1297  PosePackData pd = pose_to_pack_data(pose);
1298 
1299  TRcs << "spheres len: " << pd.spheres.size() << std::endl;
1300  TRcs << "centers len: " << pd.centers.size() << std::endl;
1301 
1302  SasaOptions opts;
1303  opts.prune_max_iters = 999;
1304  opts.prune_max_delta = 0;
1305  opts.num_cav_ball_layers = 10;
1306  opts.frac_cav_ball_required_exposed = 0.00;
1307  opts.area_cav_ball_required_exposed = 0.00;
1308  opts.surrounding_sasa_smoothing_window = 3;
1309  opts.min_cav_ball_radius = option[ OptionKeys::packstat::min_cav_ball_radius ]();
1310  opts.min_cluster_overlap = option[ OptionKeys::packstat::min_cluster_overlap ]();
1311  opts.cluster_min_volume = option[ OptionKeys::packstat::cluster_min_volume ]();
1312  for( PackstatReal pr = 3.0; pr > 2.0; pr -= 0.2 ) opts.probe_radii.push_back(pr);
1313  for( PackstatReal pr = 2.0; pr >= 0.7; pr -= 0.1 ) opts.probe_radii.push_back(pr);
1314  opts.prune_cavity_burial_probe_radii.push_back( burial_radius );
1315  if( surface_accessibility ) {
1316  for( PackstatReal pr = burial_radius-0.1; pr >= 0.1; pr -= 0.1 ) {
1317  opts.prune_cavity_burial_probe_radii.push_back(pr);
1318  }
1319  }
1320 
1321  //TRps << "compute MSAs" << std::endl;
1322  SasaResultOP sr = compute_sasa( pd.spheres, opts );
1323 
1324  ////////////////////////////////////////////////////////////////////////////////////////////////
1325  CavBalls cavballs = sr->cavballs;
1326  //TRps << "pruning hidden cav balls " << cavballs.size() << std::endl;
1327  cavballs = prune_hidden_cavity_balls( cavballs, opts );
1328 
1329  //TRps << "pruning exposed cav balls " << cavballs.size() << std::endl;
1330  cavballs = prune_cavity_balls( pd.spheres, cavballs, opts );
1331 
1332  //TRps << "compute cav ball volumes " << cavballs.size() << std::endl;
1333  compute_cav_ball_volumes( cavballs, opts );
1334 
1335  vector1< CavityBallCluster > clusters = compute_cav_ball_clusters( cavballs, opts );
1336 
1337  for( Size i = 1; i <= clusters.size(); i++ ) {
1338  for( Size j = 1; j <= clusters[i].cavballs.size(); j++ ) {
1339  if( clusters[i].cavballs[j].radius() > 0.7 )
1340  out << clusters[i].cavballs[j].hetero_atom_line( pose.total_residue()+i, i, 0.6 ) << std::endl;
1341  }
1342  }
1343 
1344  // std::ofstream dbg("DEBUG.pdb");
1345  // pose.dump_pdb(dbg);
1346  // for( Size i = 1; i <= clusters.size(); i++ ) {
1347  // for( Size j = 1; j <= clusters[i].cavballs.size(); j++ ) {
1348  // dbg << clusters[i].cavballs[j].hetero_atom_line( pose.total_residue()+i, i ) << std::endl;
1349  // }
1350  // }
1351  // dbg.close();
1352 
1353 }
1354 
1355 
1356 } // namespace packstat
1357 } // namespace scoring
1358 } // namespace core
1359 
1360 
1361 
1362 
1363 
1364