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