Index: kernel/include/IMP/pair_scores/DistancePairScore.h
===================================================================
--- kernel/include/IMP/pair_scores/DistancePairScore.h	(revision 333)
+++ kernel/include/IMP/pair_scores/DistancePairScore.h	(working copy)
@@ -26,6 +26,18 @@
   virtual void show(std::ostream &out=std::cout) const;
 };
 
+namespace internal {
+//! An internal helper function for evaluating distance potentials
+/**
+   The function applies f to scale*(distance-offset).
+ */
+Float evaluate_distance_pair_score(Particle *a, Particle *b,
+                                   DerivativeAccumulator *da,
+                                   UnaryFunction *f,
+                                   Float offset,
+                                   Float scale);
+}
+
 } // namespace IMP
 
 #endif  /* __IMP_DISTANCE_PAIR_SCORE_H */
Index: kernel/src/pair_scores/DistancePairScore.cpp
===================================================================
--- kernel/src/pair_scores/DistancePairScore.cpp	(revision 333)
+++ kernel/src/pair_scores/DistancePairScore.cpp	(working copy)
@@ -12,14 +12,17 @@
 namespace IMP
 {
 
-static const Float MIN_DISTANCE = .00001;
-
-DistancePairScore::DistancePairScore(UnaryFunction *f): f_(f){}
-
-Float DistancePairScore::evaluate(Particle *a, Particle *b,
-                                  DerivativeAccumulator *da)
+namespace internal {
+  static const Float MIN_DISTANCE = .00001;
+  Float evaluate_distance_pair_score(Particle *a, Particle *b,
+                                     DerivativeAccumulator *da,
+                                     UnaryFunction *f,
+                                     Float offset,
+                                     Float scale)
 {
-  IMP_CHECK_OBJECT(f_);
+  IMP_CHECK_OBJECT(f);
+  IMP_CHECK_OBJECT(a);
+  IMP_CHECK_OBJECT(b);
 
   Float d2 = 0, delta[3];
   Float score;
@@ -32,6 +35,8 @@
   }
 
   Float distance = std::sqrt(d2);
+ 
+  Float shifted_distance = scale*(distance - offset);
 
   // if needed, calculate the partial derivatives of the scores with respect
   // to the particle attributes
@@ -39,23 +44,34 @@
   if (da && distance >= MIN_DISTANCE) {
     Float deriv;
 
-    score = (*f_)(distance, deriv);
+    score = (*f)(shifted_distance, deriv);
 
     for (int i = 0; i < 3; ++i) {
       Float d = delta[i] / distance * deriv;
       d0.add_to_coordinate_derivative(i, d, *da);
       d1.add_to_coordinate_derivative(i, -d, *da);
     }
-  } else {
+  }
+
+  else {
     // calculate the score based on the distance feature
-    score = (*f_)(distance);
+    score = (*f)(shifted_distance);
   }
 
   IMP_LOG(VERBOSE, "For " << a->get_index() << " and " << b->get_index()
           << " distance: " << distance << " score: " << score << std::endl);
   return score;
 }
+}
 
+DistancePairScore::DistancePairScore(UnaryFunction *f): f_(f){}
+
+Float DistancePairScore::evaluate(Particle *a, Particle *b,
+                                  DerivativeAccumulator *da)
+{
+  return internal::evaluate_distance_pair_score(a,b, da, f_.get(), 0,1);
+}
+
 void DistancePairScore::show(std::ostream &out) const
 {
   out << "DistancePairScore using ";
Index: kernel/src/pair_scores/SphereDistancePairScore.cpp
===================================================================
--- kernel/src/pair_scores/SphereDistancePairScore.cpp	(revision 333)
+++ kernel/src/pair_scores/SphereDistancePairScore.cpp	(working copy)
@@ -6,14 +6,11 @@
  */
 
 #include "IMP/pair_scores/SphereDistancePairScore.h"
-#include "IMP/decorators/XYZDecorator.h"
 #include "IMP/UnaryFunction.h"
+#include "IMP/pair_scores/DistancePairScore.h"
 
 namespace IMP
 {
-
-static const Float MIN_DISTANCE = .00001;
-
 SphereDistancePairScore::SphereDistancePairScore(UnaryFunction *f,
                                                  FloatKey radius) :
     f_(f), radius_(radius)
@@ -23,46 +20,10 @@
 Float SphereDistancePairScore::evaluate(Particle *a, Particle *b,
                                         DerivativeAccumulator *da)
 {
-  IMP_CHECK_OBJECT(f_);
-
-  Float d2 = 0, delta[3];
-  Float score;
-
-  XYZDecorator d0 = XYZDecorator::cast(a);
-  XYZDecorator d1 = XYZDecorator::cast(b);
-  for (int i = 0; i < 3; ++i) {
-    delta[i] = d0.get_coordinate(i) - d1.get_coordinate(i);
-    d2 += square(delta[i]);
-  }
-
-  Float distance = std::sqrt(d2);
   Float ra = a->get_value(radius_);
   Float rb = b->get_value(radius_);
-  Float shifted_distance = distance - (ra + rb);
-
-  // if needed, calculate the partial derivatives of the scores with respect
-  // to the particle attributes
-  // avoid division by zero if the distance is too small
-  if (da && distance >= MIN_DISTANCE) {
-    Float deriv;
-
-    score = (*f_)(shifted_distance, deriv);
-
-    for (int i = 0; i < 3; ++i) {
-      Float d = delta[i] / distance * deriv;
-      d0.add_to_coordinate_derivative(i, d, *da);
-      d1.add_to_coordinate_derivative(i, -d, *da);
-    }
-  }
-
-  else {
-    // calculate the score based on the distance feature
-    score = (*f_)(shifted_distance);
-  }
-
-  IMP_LOG(VERBOSE, "For " << a->get_index() << " and " << b->get_index()
-          << " distance: " << distance << " score: " << score << std::endl);
-  return score;
+  return internal::evaluate_distance_pair_score(a,b, da, f_.get(), 
+                                                ra+rb, 1);
 }
 
 void SphereDistancePairScore::show(std::ostream &out) const