diff --git a/include/GaussianEMRestraint.h b/include/GaussianEMRestraint.h
index e85573d52389f8a21a52b1215b443f4e4d0c88b4..dbc9d110dbafcd80baa727783bea64203abb85a3 100755
--- a/include/GaussianEMRestraint.h
+++ b/include/GaussianEMRestraint.h
@@ -14,6 +14,7 @@
 #include <IMP/container/ListSingletonContainer.h>
 #include <IMP/container_macros.h>
 #include <IMP/core/XYZ.h>
+#include <IMP/core/SerialMover.h>
 #include <IMP/core/Gaussian.h>
 #include <IMP/algebra/Gaussian3D.h>
 #include <IMP/container/CloseBipartitePairContainer.h>
@@ -104,7 +105,7 @@ class IMPBAYESIANEMEXPORT GaussianEMRestraint : public Restraint
     return exp(-unprotected_evaluate(NULL));
   }
 
-  //! Pre-calculate the density-density and model-model scores
+  //! Pre-calculate the data-data overlap
   /** This is automatically called by the constructor.
       You only need to call it manually if you change Gaussian variances
   */
@@ -119,7 +120,9 @@ class IMPBAYESIANEMEXPORT GaussianEMRestraint : public Restraint
   virtual double
     unprotected_evaluate(IMP::DerivativeAccumulator *accum)
     const IMP_OVERRIDE;
+  void compute_individual_scores(const Ints &indices) const IMP_OVERRIDE;
   virtual IMP::ModelObjectsTemp do_get_inputs() const IMP_OVERRIDE;
+	void set_incremental(IMP::core::SerialMover *sm);
   void show(std::ostream &out) const { out << "GEM restraint"; }
   IMP_OBJECT_METHODS(GaussianEMRestraint);
 
@@ -133,23 +136,24 @@ class IMPBAYESIANEMEXPORT GaussianEMRestraint : public Restraint
   Float normalization_;
   ParticleIndexes slope_ps_; //experiment
   std::vector<Float> vec_score_dd_;
-  std::vector<Float> vec_score_dm_;
+	std::vector<Float> slope_scores;
+
+	std::vector<Ints > density_indexes_;
+	std::vector<Ints > model_indexes_;
+	IMP::core::SerialMover *serial_mover_;
+
+	// these things are made mutable because they have to be modified by unprotected_evaluate that is const-qualified. 
+  mutable std::vector<Float> vec_score_dm_;
+	mutable std::vector<Float> slope_scores_;
 
   Float cached_score_term_; 
+	Ints cached_model_indices_;
 
 	Float cutoff_dist_;
 
 	Float score_gaussian_overlap (Model *m,
 	                             ParticleIndexPair pp,
 															 Eigen::Vector3d * deriv)const;
-
-
-  //variables needed to tabulate the exponential
-  Floats exp_grid_;
-  double invdx_;
-  double argmax_;
-
-
 };
 
 IMPBAYESIANEM_END_NAMESPACE
diff --git a/pyext/src/restraint.py b/pyext/src/restraint.py
index d44b46e8d061c4fac40d17334cc7be1673f6b12a..968414258706e1ff6da6c07811af089e47bbefc4 100755
--- a/pyext/src/restraint.py
+++ b/pyext/src/restraint.py
@@ -182,6 +182,9 @@ class GaussianEMRestraintWrapper(object):
         self.rs.add_restraint(self.gaussianEM_restraint)
         self.set_weight(weight)
 
+    def set_incremental(self,m):
+        self.gaussianEM_restraint.set_incremental(m)
+
     def center_target_density_on_model(self):
         '''
         aligns the center of mass of the target GMM on the center of mass of the model
diff --git a/src/GaussianEMRestraint.cpp b/src/GaussianEMRestraint.cpp
index f3ac2443f74e33c86568550224fb3127f803448d..8bf9e0df0bd8043e8abc8e97cff7aa81bc7cbad9 100755
--- a/src/GaussianEMRestraint.cpp
+++ b/src/GaussianEMRestraint.cpp
@@ -16,6 +16,7 @@
 #include <IMP/isd/Scale.h>
 #include <IMP/isd/em_utilities.h>
 #include <limits>
+#include <algorithm>
 
 IMPBAYESIANEM_BEGIN_NAMESPACE
 
@@ -27,7 +28,7 @@ GaussianEMRestraint::GaussianEMRestraint(Model *mdl, ParticleIndexes model_ps,
                                          bool update_model, bool backbone_slope,
                                          std::string name)
     : Restraint(mdl, name), model_ps_(model_ps), density_ps_(density_ps),
-      global_sigma_(global_sigma), slope_(slope), update_model_(update_model), cutoff_dist_(cutoff_dist) {
+      global_sigma_(global_sigma), slope_(slope), update_model_(update_model), cutoff_dist_(cutoff_dist), serial_mover_(NULL) {
 
   msize_ = model_ps.size();
   dsize_ = density_ps.size();
@@ -46,12 +47,19 @@ GaussianEMRestraint::GaussianEMRestraint(Model *mdl, ParticleIndexes model_ps,
                     "Density particles must have Mass");
   }
 
-	vec_score_dm_.reserve(dsize_);
+	vec_score_dm_.reserve(dsize_*msize_);
+	for (int j(0) ; j < dsize_*msize_ ; ++j){
+		vec_score_dm_.push_back(0.0);
+	}
 
-	for (int j(0) ; j < dsize_ ; ++j){
-		vec_score_dm_[j]=0.0;
+	slope_scores_.reserve(msize_);
+	cached_model_indices_.reserve(msize_);
+	for (int j(0) ; j < msize_ ; ++j){
+		slope_scores_.push_back(0.0);
+		cached_model_indices_.push_back(j);
 	}
 
+
   compute_initial_scores();
 
   if (backbone_slope) {
@@ -95,23 +103,33 @@ void GaussianEMRestraint::compute_initial_scores() {
   cached_score_term_ += 0.5 * std::log(IMP::PI);
   cached_score_term_ -= std::lgamma(dsize_ / 2.0);
 
+	compute_individual_scores(cached_model_indices_);
+
 }
 
-double
-GaussianEMRestraint::unprotected_evaluate(DerivativeAccumulator *accum) const {
-  Float scale = IMP::isd::Scale(get_model(), global_sigma_).get_scale();
-  Eigen::Vector3d deriv;
+Ints get_changed_indices(
+	const IMP::core::SerialMover * sm,
+	const std::vector<Ints> &indices,
+	int num_ps){
 
-  Float slope_score = 0.0;
+	Ints ret;
+	Ints changed_indices;
+
+	const int i = sm->get_mover_index();
+	return indices[i];
+}
 
-  std::vector<Float> vec_score_dm_(dsize_, 0.0);
+
+void
+GaussianEMRestraint::compute_individual_scores(const Ints &changed_model_ps) const {
 
 	double determinant;
 	bool invertible;
 	Eigen::Matrix3d inverse = Eigen::Matrix3d::Zero();
-	for (int i(0) ; i < msize_ ; ++i){
-		Float min_dist = std::numeric_limits<Float>::max();
+	for (int l(0) ; l < changed_model_ps.size() ; ++l){
+		const int i=changed_model_ps[l];
 		const ParticleIndex pi(model_ps_[i]);
+		Float min_dist = std::numeric_limits<Float>::max();
 		core::Gaussian g1(get_model(),pi);
 		const Float m1 = atom::Mass(get_model(),pi).get_mass();
 		Eigen::Matrix3d cov1 = g1.get_global_covariance();
@@ -125,24 +143,46 @@ GaussianEMRestraint::unprotected_evaluate(DerivativeAccumulator *accum) const {
 			if (sd < min_dist) {
 				min_dist = sd;
 			}
-			if (sd < cutoff_dist_){
+			const Float xyzrdist = IMP::core::get_distance(IMP::core::XYZR(get_model(), pi), IMP::core::XYZR(get_model(), pj));
+			if (xyzrdist < cutoff_dist_){
 				Eigen::Matrix3d covar = cov1 + g2.get_global_covariance();
 				covar.computeInverseAndDetWithCheck(inverse,determinant,invertible);
 				const Float mass12 = m1 * atom::Mass(get_model(),pj).get_mass();
 				const Eigen::Vector3d tmp = inverse*v;
 				const Float score = mass12 * 0.06349363593424097 / (std::sqrt(determinant)) * std::exp(-0.5*v.transpose()*tmp);
-				vec_score_dm_[j] += score;
+				vec_score_dm_[n] = score;
 			}
 		}
-		slope_score += slope_ * min_dist;
+		slope_scores_[i] = slope_ * min_dist;
 	}
+}
 
+double
+GaussianEMRestraint::unprotected_evaluate(DerivativeAccumulator *accum) const {
+  Float scale = IMP::isd::Scale(get_model(), global_sigma_).get_scale();
+  Eigen::Vector3d deriv;
+
+
+	if(serial_mover_ && serial_mover_->get_mover_index()>=0){
+		Ints changed_model_ps = get_changed_indices(serial_mover_, model_indexes_, model_ps_.size());
+		compute_individual_scores(changed_model_ps);
+	} else{
+		compute_individual_scores(cached_model_indices_);
+	}
+
+	Float slope_score = 0.0;
+	for (int i(0) ; i < msize_ ; ++i){
+		slope_score+=slope_scores_[i];
+	}
 
   double logterm = 0.0;
 	for (int j(0) ; j < dsize_ ; ++j){
-		const ParticleIndex pj(density_ps_[j]);
     const Float scoredd = vec_score_dd_[j];
-    Float scoredm = vec_score_dm_[j];
+    Float scoredm = 0.0;
+		for (int i(0) ; i < msize_ ; ++i){
+			const int n = i*dsize_ + j;
+			scoredm+=vec_score_dm_[n];
+		}
     const Float lt =
         std::log(scale * (scoredm + 0.0000000001) / (scoredd + 0.0000000001));
     logterm += lt * lt;
@@ -152,6 +192,46 @@ GaussianEMRestraint::unprotected_evaluate(DerivativeAccumulator *accum) const {
   return log_score;
 }
 
+Ints get_all_indexes(IMP::core::MonteCarloMover *m, const ParticleIndexes &ref){
+	Ints ret;
+	ModelObjectsTemp inputs = m->get_inputs();
+	for(int i(0) ; i<inputs.size() ; ++i){
+		ModelObject *o = inputs[i];
+		Particle *p = dynamic_cast<Particle *>(o);
+		if(p && IMP::core::Gaussian::get_is_setup(p)){
+			for(int j(0) ; j<ref.size() ; ++j){
+				if(p->get_index().get_index() == ref[j].get_index()){
+					ret.push_back(j);
+				}
+			}
+		}
+		else if(p && IMP::core::RigidBody::get_is_setup(p)){
+			ParticleIndexes pis = IMP::core::RigidBody(p).get_body_member_particle_indexes();
+			for (int k(0) ; k<pis.size() ; ++k){
+				for(int j(0) ; j<ref.size() ; ++j){
+					if(pis[k].get_index() == ref[j].get_index()){
+						ret.push_back(j);
+					}
+				}				
+			}
+		}
+	}
+	std::sort(ret.begin(), ret.end());
+	return ret;
+}
+
+void GaussianEMRestraint::set_incremental(IMP::core::SerialMover *sm){
+	serial_mover_ = sm;
+	model_indexes_.clear();
+	density_indexes_.clear();
+	const IMP::core::MonteCarloMovers movers = sm->get_movers();
+	for(int i(0) ; i<movers.size() ; ++i){
+		IMP::core::MonteCarloMover *m=movers[i];
+		Ints model_ps_in_mover = get_all_indexes(m, model_ps_);
+		model_indexes_.push_back(model_ps_in_mover);
+	}
+}
+
 
 /* Return all particles whose attributes are read by the restraints. To
    do this, ask the pair score what particles it uses.*/