SecondaryStructureResidue setup_coarse_secondary_structure_residue(
    const Particles &ssr_ps, Model *mdl,
    bool winner_takes_all_per_res) {
  Floats scores;
  scores.push_back(0.0);
  scores.push_back(0.0);
  scores.push_back(0.0);
  int count = 0;
  for (Particles::const_iterator p = ssr_ps.begin(); p != ssr_ps.end();
       ++p) {
    IMP_USAGE_CHECK(SecondaryStructureResidue::get_is_setup(*p),
                    "all particles must be SecondaryStructureResidues");
    SecondaryStructureResidue ssr(*p);
    Floats tmp_scores;
    tmp_scores.push_back(ssr.get_prob_helix());
    tmp_scores.push_back(ssr.get_prob_strand());
    tmp_scores.push_back(ssr.get_prob_coil());
    int max_i = 0;
    Float max = 0.0;
    for (int i = 0; i < 3; i++) {
      if (tmp_scores[i] > max) {
        max = tmp_scores[i];
        max_i = i;
      }
      if (!winner_takes_all_per_res) scores[i] += tmp_scores[i];
    }
    if (winner_takes_all_per_res) scores[max_i] += 1.0;
    count++;
  }
  IMP_NEW(Particle, coarse_p, (mdl));
  SecondaryStructureResidue ssres = SecondaryStructureResidue::setup_particle(
      coarse_p, scores[0] / count, scores[1] / count, scores[2] / count);
  return ssres;
}
Beispiel #2
0
/// A thread-safe version of CalcSummary.  BlockFile::CalcSummary
/// uses a static summary array across the class, which we can't use.
/// Get a buffer containing a summary block describing this sample
/// data.  This must be called by derived classes when they
/// are constructed, to allow them to construct their summary data,
/// after which they should write that data to their disk file.
///
/// This method also has the side effect of setting the mMin, mMax,
/// and mRMS members of this class.
///
/// Unlike BlockFile's implementation You SHOULD DELETE the returned buffer.
/// this is protected so it shouldn't be hard to deal with - just override
/// all BlockFile methods that use this method.
///
/// @param buffer A buffer containing the sample data to be analyzed
/// @param len    The length of the sample data
/// @param format The format of the sample data.
void *ODDecodeBlockFile::CalcSummary(samplePtr buffer, size_t len,
                             sampleFormat format, ArrayOf<char> &cleanup)
{
   cleanup.reinit(mSummaryInfo.totalSummaryBytes);
   char* localFullSummary = cleanup.get();

   memcpy(localFullSummary, bheaderTag, bheaderTagLen);

   float *summary64K = (float *)(localFullSummary + mSummaryInfo.offset64K);
   float *summary256 = (float *)(localFullSummary + mSummaryInfo.offset256);

   Floats floats;
   float *fbuffer;

   //mchinen: think we can hack this - don't allocate and copy if we don't need to.,
   if(format==floatSample)
   {
      fbuffer = (float*)buffer;
   }
   else
   {
      floats.reinit(len);
      fbuffer = floats.get();
      CopySamples(buffer, format,
               (samplePtr)fbuffer, floatSample, len);
   }

   BlockFile::CalcSummaryFromBuffer(fbuffer, len, summary256, summary64K);

   return localFullSummary;
}
Beispiel #3
0
TEST(Neighbors,CoverTreeDistanceNeighbors)
{
	typedef std::vector<float> Floats;
	const int N = 100;
	const int k = 10;

	Floats floats;
	for (int i=0;i<N;i++) 
		floats.push_back(float(i));

	float_distance_callback fdc;
	tapkee::tapkee_internal::Neighbors neighbors = 
		tapkee::tapkee_internal::find_neighbors(tapkee::CoverTree, floats.begin(), floats.end(),
				tapkee::tapkee_internal::PlainDistance<Floats::iterator,float_distance_callback>(fdc), k, true);

	for (int i=0;i<N;i++)
	{
		// total number of found neighbors is k
		ASSERT_EQ(neighbors[i].size(),k);
		std::set<float> neighbors_set;
		for (int j=0;j<k;j++) 
			neighbors_set.insert(neighbors[i][j]);
		// there are no repeated values
		ASSERT_EQ(neighbors_set.size(),k);
		// the vector is not a neighbor of itself
		ASSERT_EQ(neighbors_set.find(floats[i]),neighbors_set.end());
		// check neighbors
		int k_left = std::min(i,k/2);
		int k_right = std::min(N-i-1,k/2);
		for (int j=0; j<k_left; j++) 
			ASSERT_NE(neighbors_set.find(floats[i-j-1]),neighbors_set.end());
		for (int j=0; j<k_right; j++) 
			ASSERT_NE(neighbors_set.find(floats[i+j+1]),neighbors_set.end());
	}
}
Floats CysteineCrossLinkData::get_omegas(Floats fmods, double omega0) const {
  Floats omegas;
  for (unsigned n = 0; n < fmods.size(); ++n) {

    double cumul = 0;
    double cumul2 = 0;

    for (unsigned j = 1; j < omega_grid_.size(); ++j) {
      double omj = omega_grid_[j];
      double omjm1 = omega_grid_[j - 1];
      double dom = omj - omjm1;

      double priorj = get_omega_prior(omj, omega0);
      double priorjm1 = get_omega_prior(omjm1, omega0);

      double pj = get_element(fexp_, fmods[n], omj) * priorj;
      double pjm1 = get_element(fexp_, fmods[n], omjm1) * priorjm1;

      double pj2 = get_element(fexp_, fmods[n], omj) * priorj * omj;
      double pjm12 = get_element(fexp_, fmods[n], omjm1) * priorjm1 * omjm1;

      cumul += (pj + pjm1) / 2.0 * dom;
      cumul2 += (pj2 + pjm12) / 2.0 * dom;
    }

    omegas.push_back(cumul2 / cumul);
  }
  return omegas;
}
Floats GaussianProcessInterpolation::get_posterior_covariance_derivative(
    Floats x, bool) const {
  IMP_Eigen::VectorXd mat(get_posterior_covariance_derivative(x));
  Floats tmp;
  for (unsigned j = 0; j < mat.rows(); j++) tmp.push_back(mat(j));
  return tmp;
}
Beispiel #6
0
Floats FStudentT::evaluate_derivative_FX(const Floats FXs) const {
  Floats dervs;
  double c = (N_ + nu_) / IMP::square(sigma_) / (nu_ + t2_);
  for (unsigned int i = 0; i < FXs.size(); i++) {
    dervs.push_back(c * (FXs[i] - FM_));
  }
  return dervs;
}
Beispiel #7
0
Floats ReplicaExchange::create_temperatures(double tmin,double tmax,int nrep)
{
 Floats temp;
 double tfact=exp(log(tmax/tmin)/double(nrep-1));
 for(int i=0;i<nrep;++i) {
  temp.push_back(tmin*pow(tfact,i));
 }
 return temp;
}
Beispiel #8
0
Floats CrossLinkData::get_marginal_elements(double sigma, Floats dists) const {
  Floats probs;
  unsigned is = get_closest(sigma_grid_, sigma);
  for (unsigned n = 0; n < dists.size(); n++) {

    unsigned id = get_closest(dist_grid_, dists[n]);
    probs.push_back(grid_[is][id]);
  }
  return probs;
}
Floats CysteineCrossLinkData::get_nonmarginal_elements(double fexp,
                                                       Floats fmods,
                                                       double omega) const {
  Floats probs;

  for (unsigned n = 0; n < fmods.size(); n++) {
    probs.push_back(get_element(fexp, fmods[n], omega));
  }
  return probs;
}
Beispiel #10
0
void write_cmm(const std::string &cmm_filename,
               const std::string &marker_set_name, const AnchorsData &ad) {
  Floats radii;
  // algebra::get_enclosing_sphere(dpa.get_cluster_vectors(i));
  radii.insert(radii.begin(), ad.get_number_of_points(), 5.);
  std::ofstream out;
  out.open(cmm_filename.c_str(), std::ios::out);
  write_cmm_helper(out, marker_set_name, ad.points_, ad.edges_, radii);
  out.close();
}
FloatsList GaussianProcessInterpolationRestraint::get_hessian(bool) const {
  IMP_Eigen::MatrixXd tmp(get_hessian());
  FloatsList ret;
  for (unsigned i = 0; i < tmp.rows(); ++i) {
    Floats buf;
    for (unsigned j = 0; j < tmp.cols(); ++j) buf.push_back(tmp(i, j));
    ret.push_back(buf);
  }
  return ret;
}
FloatsList GaussianProcessInterpolation::get_data_variance() const {
  FloatsList ret;
  IMP_Eigen::MatrixXd S(get_S());
  for (unsigned i = 0; i < M_; i++) {
    Floats val;
    for (unsigned j = 0; j < M_; j++) val.push_back(S(i, j));
    ret.push_back(val);
  }
  return ret;
}
IMPISD_BEGIN_NAMESPACE

CysteineCrossLinkData::CysteineCrossLinkData(double fexp, Floats fmod_grid,
                                             Floats omega_grid,
                                             Floats omega0_grid, int prior_type)
    : Object("Data Structure for CysteineCrossLinkRestraint %1%") {
  prior_type_ = prior_type;
  // fexp is the experimental frequency
  // fmod is the model frequency
  // omega0 is the typical value for omega, i.e., the experimental uncertainty

  // this constructor calculates the marginal likelihood using a
  // truncated gaussian function
  // to account for outliers

  // Store omega0 grid
  omega0_grid_ = omega0_grid;

  // Store the fmod grid
  fmod_grid_ = fmod_grid;

  // Store omega grid
  omega_grid_ = omega_grid;

  fexp_ = fexp;

  for (unsigned k = 0; k < omega0_grid_.size(); ++k) {

    double omega0 = omega0_grid_[k];

    Floats grid;

    for (unsigned i = 0; i < fmod_grid_.size(); ++i) {

      double fmod = fmod_grid_[i];

      double cumul = 0;
      for (unsigned j = 1; j < omega_grid_.size(); ++j) {

        double omj = omega_grid_[j];
        double omjm1 = omega_grid_[j - 1];
        double dom = omj - omjm1;

        double priorj = get_omega_prior(omj, omega0);
        double priorjm1 = get_omega_prior(omjm1, omega0);

        double pj = get_element(fexp_, fmod, omj) * priorj;
        double pjm1 = get_element(fexp_, fmod, omjm1) * priorjm1;
        cumul += (pj + pjm1) / 2.0 * dom;
      }
      grid.push_back(cumul);
    }
    grid_.push_back(grid);
  }
}
Beispiel #14
0
algebra::Vector3Ds ProbabilisticAnchorGraph::get_particle_anchors(
    Particle *p, float min_prob) const {
  Floats probs = get_particle_probabilities(p);
  algebra::Vector3Ds anchors;
  for (unsigned int i = 0; i < probs.size(); i++) {
    if (probs[i] >= min_prob) {
      anchors.push_back(positions_[i]);
    }
  }
  return anchors;
}
Floats CysteineCrossLinkData::get_marginal_elements(Floats fmods,
                                                    double omega0) const {
  Floats probs;
  unsigned is = get_closest(omega0_grid_, omega0);
  for (unsigned n = 0; n < fmods.size(); n++) {

    unsigned id = get_closest(fmod_grid_, fmods[n]);
    probs.push_back(grid_[is][id]);
  }
  return probs;
}
FloatsList GaussianProcessInterpolation::get_posterior_covariance_hessian(
    Floats x, bool) const {
  IMP_Eigen::MatrixXd mat(get_posterior_covariance_hessian(x));
  FloatsList ret;
  for (unsigned j = 0; j < mat.rows(); j++) {
    Floats tmp;
    for (unsigned i = 0; i < mat.cols(); i++) tmp.push_back(mat(i, j));
    ret.push_back(tmp);
  }
  return ret;
}
Beispiel #17
0
 algebra::VectorKD get_embedding(const Subset &s,
                                 const Assignment &a,
                                 ParticleStatesTable *pst){
   Floats embed;
  for (unsigned int i=0; i< s.size(); ++i) {
    algebra::VectorKD cur
        = pst->get_particle_states(s[i])->get_embedding(a[i]);
    embed.insert(embed.end(), cur.coordinates_begin(),
                 cur.coordinates_end());
  }
  return embed;
 }
IMPCORE_BEGIN_NAMESPACE

OpenCubicSpline::OpenCubicSpline(const Floats &values,
                                 Float minrange, Float spacing,
                                 bool extend) :
  spacing_(spacing), inverse_spacing_(1.0/spacing_),
  spline_(values, spacing_, inverse_spacing_),
  minrange_(minrange), maxrange_(minrange_ + spacing_ * (values.size() - 1)),
  extend_(extend)
{
  IMP_USAGE_CHECK(spacing >0, "The spacing between values must be positive.");
  IMP_USAGE_CHECK(values.size() >=1, "You must provide at least one value.");
}
Beispiel #19
0
IMPALGEBRA_BEGIN_NAMESPACE

LinearFit2D::LinearFit2D(const algebra::Vector2Ds& data,
                         const Floats &errors) {
  // check that there are at least 3 points
  IMP_USAGE_CHECK(data.size() > 1,
                  "At least 2 points are required for LinearFit2D "
                  << data.size() << " given");
  IMP_USAGE_CHECK(errors.empty() || errors.size()==data.size(),
                  "Either there must be no error bars given or one per"
                  << " point.");
  find_regression(data, errors);
  evaluate_error(data, errors);
}
Beispiel #20
0
Floats CrossLinkData::get_nonmarginal_elements(double sigmai,
                                               Floats dists) const {
  Floats probs;
  if (bias_) {
    for (unsigned n = 0; n < dists.size(); n++) {
      probs.push_back(get_biased_element(dists[n], sigmai));
    }
  }
  if (!bias_) {
    for (unsigned n = 0; n < dists.size(); n++) {
      probs.push_back(get_unbiased_element(dists[n], sigmai));
    }
  }
  return probs;
}
Beispiel #21
0
IMPSCOREFUNCTOR_BEGIN_INTERNAL_NAMESPACE

RawOpenCubicSpline::RawOpenCubicSpline(const Floats &values, double spacing,
                                       double inverse_spacing)
    : values_(values) {
  IMP_USAGE_CHECK(spacing > 0, "The spacing between values must be positive.");
  IMP_USAGE_CHECK(values.size() >= 1, "You must provide at least one value.");
  int npoints = values_.size();
  // Precalculate second derivatives for a natural cubic spline (open) by
  // inversion of the tridiagonal matrix (Thomas algorithm)
  second_derivs_.resize(npoints);
  Floats tmp(npoints);

  // Forward elimination phase
  second_derivs_[0] = 0.;
  tmp[0] = 0.;

  double inverse_doublespacing = 1.0 / (spacing + spacing);
  for (int i = 1; i < npoints - 1; ++i) {
    Float m = 0.5 * second_derivs_[i - 1] + 2.;
    second_derivs_[i] = -0.5 / m;
    tmp[i] = (6. * ((values_[i + 1] - values_[i]) * inverse_spacing -
                    (values_[i] - values_[i - 1]) * inverse_spacing) *
                  inverse_doublespacing -
              0.5 * tmp[i - 1]) /
             m;
  }
  // Backward substitution phase
  second_derivs_[npoints - 1] = 0.;
  for (int i = npoints - 2; i >= 0; --i) {
    second_derivs_[i] = second_derivs_[i] * second_derivs_[i + 1] + tmp[i];
  }
  /*IMP_LOG_TERSE( "Initialized spline with " << values.size() << " values "
    << "with spacing " << spacing << std::endl);*/
}
Beispiel #22
0
void ProbabilisticAnchorGraph::set_particle_probabilities_on_anchors(
    Particle *p, FittingSolutionRecords sols) {
  IMP_USAGE_CHECK(sols.size() > 0, "no solutions provided\n");
  IMP_NEW(algebra::NearestNeighborD<3>, nn, (positions_));
  Ints anchor_counters;
  anchor_counters.insert(anchor_counters.end(), positions_.size(), 0);
  for (unsigned int i = 0; i < sols.size(); i++) {
    algebra::Vector3D loc = sols[i].get_fit_transformation().get_transformed(
        core::XYZ(p).get_coordinates());
    anchor_counters[nn->get_nearest_neighbor(loc)]++;
  }
  Floats probs;
  for (unsigned int i = 0; i < anchor_counters.size(); i++) {
    probs.push_back(1. * anchor_counters[i] / sols.size());
  }
  particle_to_anchor_probabilities_[p] = probs;
}
Beispiel #23
0
Floats CrossLinkData::get_omegas(double sigma, Floats dists) const {
  Floats omegas;
  for (unsigned n = 0; n < dists.size(); ++n) {

    double cumul = 0;
    double cumul2 = 0;

    if (!bias_) {
      for (unsigned j = 1; j < omega_grid_.size(); ++j) {
        double omj = omega_grid_[j];
        double omjm1 = omega_grid_[j - 1];
        double dom = omj - omjm1;

        double pj = get_unbiased_element(dists[n], omj * sigma) / omj;
        double pjm1 = get_unbiased_element(dists[n], omjm1 * sigma) / omjm1;

        double pj2 = get_unbiased_element(dists[n], omj * sigma);
        double pjm12 = get_unbiased_element(dists[n], omjm1 * sigma);

        cumul += (pj + pjm1) / 2.0 * dom;
        cumul2 += (pj2 + pjm12) / 2.0 * dom;
      }
    }

    if (bias_) {
      for (unsigned j = 1; j < omega_grid_.size(); ++j) {
        double omj = omega_grid_[j];
        double omjm1 = omega_grid_[j - 1];
        double dom = omj - omjm1;

        double pj = get_biased_element(dists[n], omj * sigma) / omj;
        double pjm1 = get_biased_element(dists[n], omjm1 * sigma) / omjm1;

        double pj2 = get_biased_element(dists[n], omj * sigma);
        double pjm12 = get_biased_element(dists[n], omjm1 * sigma);

        cumul += (pj + pjm1) / 2.0 * dom;
        cumul2 += (pj2 + pjm12) / 2.0 * dom;
      }
    }

    omegas.push_back(cumul2 / cumul);
  }
  return omegas;
}
Beispiel #24
0
IMPCORE_BEGIN_NAMESPACE

RigidBodyUmbrella::RigidBodyUmbrella(kernel::Model *m, kernel::ParticleIndex pi,
                                     kernel::ParticleIndex ref, Floats x0,
                                     double alpha, double k, std::string name)
    : Restraint(m, name), pi_(pi), ref_(ref), x0_(x0), alpha_(alpha),
      k_(k) {
  IMP_USAGE_CHECK(x0.size() == 7, "Wrong size for x0, should be 7");
}
Beispiel #25
0
void FStudentT::do_update_sufficient_statistics(Floats FXs) {
  N_ = FXs.size();
  sumFX_ = FXs[0];
  sumFX2_ = IMP::square(FXs[0]);
  LogJX_ = 0.;
  for (unsigned int i = 1; i < N_; ++i) {
    sumFX_ += FXs[i];
    sumFX2_ += IMP::square(FXs[i]);
  }
}
Beispiel #26
0
core::MonteCarloMoverResult WeightMover::do_propose() {
  IMP_OBJECT_LOG;

  // store the old weights in case of reject
  oldweights_ = w_.get_weights();

  // Draw weights from a uniform distribution of variables that sum to one
  // taken from http://stats.stackexchange.com/questions/14059/
  //                     generate-uniformly-distributed-weights-that-sum-to-unity

  // get the old x
  Floats x;
  x.push_back(oldweights_[0]);
  for (unsigned i = 1; i < oldweights_.get_dimension() - 1; ++i) {
    x.push_back(oldweights_[i] + x[i - 1]);
  }

  // zero vector in D dimension
  algebra::VectorKD zero = algebra::get_zero_vector_kd(x.size());

  // generate random perturbation of old components
  algebra::VectorKD dX =
      algebra::get_random_vector_in(algebra::SphereKD(zero, radius_));

  // add perturbation to x and apply reflective boundaries
  for (unsigned i = 0; i < x.size(); ++i) {
    if (x[i] + dX[i] > 1.0)
      x[i] = 2.0 - x[i] - dX[i];
    else if (x[i] + dX[i] < 0.0)
      x[i] = -x[i] - dX[i];
    else
      x[i] += dX[i];
  }

  // sort the new x here
  std::sort(x.begin(), x.end(), std::less<double>());

  // get the new weights
  algebra::VectorKD newweights =
      algebra::get_zero_vector_kd(oldweights_.get_dimension());

  newweights[0] = x[0];
  for (unsigned i = 1; i < newweights.get_dimension() - 1; ++i) {
    newweights[i] = x[i] - x[i - 1];
  }
  newweights[newweights.get_dimension() - 1] = 1.0 - x[x.size() - 1];

  // set the new weights
  w_.set_weights(newweights);

  return core::MonteCarloMoverResult(
      ParticleIndexes(1, w_.get_particle()->get_index()), 1.0);
}
IMPISD_BEGIN_NAMESPACE

GaussianProcessInterpolation::GaussianProcessInterpolation(
    FloatsList x, Floats sample_mean, Floats sample_std, unsigned n_obs,
    UnivariateFunction *mean_function, BivariateFunction *covariance_function,
    Particle *sigma, double sparse_cutoff)
    : Object("GaussianProcessInterpolation%1%"),
      x_(x),
      n_obs_(n_obs),
      mean_function_(mean_function),
      covariance_function_(covariance_function),
      sigma_(sigma),
      cutoff_(sparse_cutoff) {
  // O(M)
  // store dimensions
  M_ = x.size();
  N_ = x[0].size();
  sigma_val_ = Scale(sigma_).get_nuisance();
  // basic checks
  IMP_USAGE_CHECK(sample_mean.size() == M_,
                  "sample_mean should have the same size as x");
  IMP_USAGE_CHECK(sample_std.size() == M_,
                  "sample_std should have the same size as x");
  IMP_USAGE_CHECK(mean_function->get_ndims_x() == N_,
                  "mean_function should have " << N_ << " input dimensions");
  IMP_USAGE_CHECK(mean_function->get_ndims_y() == 1,
                  "mean_function should have 1 output dimension");
  IMP_USAGE_CHECK(covariance_function->get_ndims_x1() == N_,
                  "covariance_function should have "
                      << N_ << " input dimensions for first vector");
  IMP_USAGE_CHECK(covariance_function->get_ndims_x2() == N_,
                  "covariance_function should have "
                      << N_ << " input dimensions for second vector");
  IMP_USAGE_CHECK(covariance_function->get_ndims_y() == 1,
                  "covariance_function should have 1 output dimension");
  // set all flags to false = need update.
  force_mean_update();
  force_covariance_update();
  // compute needed matrices
  compute_I(sample_mean);
  compute_S(sample_std);
}
Beispiel #28
0
Floats ChainStatisticsOptimizerState::get_diffusion_coefficients() const {
  if (positions_.empty()) return Floats();
  base::Vector<algebra::Vector3Ds >
    displacements(positions_[0].size(),
                  algebra::Vector3Ds( positions_.size()-1));
  for (unsigned int i=1; i< positions_.size(); ++i) {
    algebra::Transformation3D rel
        = algebra::get_transformation_aligning_first_to_second(positions_[i-1],
                                                               positions_[i]);
    for (unsigned int j=0; j < positions_[i].size(); ++j) {
      displacements[j][i-1]= rel.get_transformed(positions_[i-1][j])
        - positions_[i][j];
    }
  }
  Floats ret;
  for (unsigned int i=0; i < displacements.size(); ++i) {
    ret.push_back(atom::get_diffusion_coefficient(displacements[i],
                                                  get_period()*get_dt()));
  }
  return ret;
}
Beispiel #29
0
void LinearFit2D::evaluate_error(const algebra::Vector2Ds& data,
                                 const Floats &errors) {
  error_ = 0.0;
  for(unsigned int i=0; i<data.size(); i++) {
    double diff = (a_*data[i][0] + b_ - data[i][1]);
    if (!errors.empty()) {
      diff/=errors[i];
    }
    error_ += diff*diff;
  }
  //std::cerr << error_ << std::endl;
}
Beispiel #30
0
/* Apply the restraint to two atoms, two Scales, one experimental value.
 */
double
AmbiguousNOERestraint::unprotected_evaluate(DerivativeAccumulator *accum) const
{
  IMP_OBJECT_LOG;
  IMP_USAGE_CHECK(get_model(),
                  "You must at least register the restraint with the model"
                  << " before calling evaluate.");

  /* compute Icalc = 1/(gamma*d^6) where d = (sum d_i^-6)^(-1/6) */
  double vol = 0;
  Floats vols;
  IMP_CONTAINER_FOREACH(PairContainer, pc_,
                        {
            core::XYZ d0(get_model(), _1[0]);
            core::XYZ d1(get_model(), _1[1]);
            algebra::Vector3D c0 = d0.get_coordinates();
            algebra::Vector3D c1 = d1.get_coordinates();
            //will raise an error if c0 == c1
            double tmp = 1.0/(c0-c1).get_squared_magnitude();
            vols.push_back(IMP::cube(tmp)); // store di^-6
            vol += vols.back();
                        });