diff --git a/src/Analyses/D0_2001_S4674421.cc b/src/Analyses/D0_2001_S4674421.cc
--- a/src/Analyses/D0_2001_S4674421.cc
+++ b/src/Analyses/D0_2001_S4674421.cc
@@ -1,197 +1,190 @@
 // -*- C++ -*-
 #include "Rivet/Analysis.hh"
 #include "Rivet/Projections/LeadingParticlesFinalState.hh"
 #include "Rivet/Projections/VetoedFinalState.hh"
 
 namespace Rivet {
 
 
   /// @brief D0 Run I differential W/Z boson cross-section analysis
   /// @author Lars Sonnenschein
   class D0_2001_S4674421 : public Analysis {
   public:
 
     /// @name Constructors etc.
     //@{
 
     /// Constructor.
     D0_2001_S4674421()
       : Analysis("D0_2001_S4674421")
     {    }
 
 
     /// @name Analysis methods
     //@{
 
     void init() {
       // Final state projection
       FinalState fs(-5.0, 5.0); // corrected for detector acceptance
       addProjection(fs, "FS");
 
       // Z -> e- e+
       LeadingParticlesFinalState eeFS(FinalState(-5.0, 5.0, 0.)); //20.);
       eeFS.addParticleIdPair(PID::ELECTRON);
       addProjection(eeFS, "eeFS");
 
       // W- -> e- nu_e~
       LeadingParticlesFinalState enuFS(FinalState(-5.0, 5.0, 0.)); //25.);
       enuFS.addParticleId(PID::ELECTRON).addParticleId(PID::NU_EBAR);
       addProjection(enuFS, "enuFS");
 
       // W+ -> e+ nu_e
       LeadingParticlesFinalState enubFS(FinalState(-5.0, 5.0, 0.)); //25.);
       enubFS.addParticleId(PID::POSITRON).addParticleId(PID::NU_E);
       addProjection(enubFS, "enubFS");
 
       // Remove neutrinos for isolation of final state particles
       VetoedFinalState vfs(fs);
       vfs.vetoNeutrinos();
       addProjection(vfs, "VFS");
 
       // Counters
       _eventsFilledW = 0.0;
       _eventsFilledZ = 0.0;
 
       // Histograms
       _h_dsigdpt_w = bookHisto1D(1, 1, 1);
       _h_dsigdpt_z = bookHisto1D(1, 1, 2);
       _h_dsigdpt_scaled_z = bookScatter2D(2, 1, 1);
     }
 
 
 
     void analyze(const Event& event) {
       const double weight = event.weight();
 
       const LeadingParticlesFinalState& eeFS = applyProjection<LeadingParticlesFinalState>(event, "eeFS");
       // Z boson analysis
       if (eeFS.particles().size() >= 2) {
         // If there is a Z candidate:
         // Fill Z pT distributions
         double deltaM2=1e30,mass2(0.);
         double pT=-1.;
         const Particles& Zdaughters = eeFS.particles();
         for(unsigned int ix=0;ix<Zdaughters.size();++ix) {
           for(unsigned int iy=ix+1;iy<Zdaughters.size();++iy) {
             if(Zdaughters[ix].pdgId()!=-Zdaughters[iy].pdgId()) continue;
             const FourMomentum pmom = Zdaughters[ix].momentum() + Zdaughters[iy].momentum();
             double mz2 = pmom.mass2();
             double dm2 = abs(mz2-sqr(91.118*GeV));
             if(dm2<deltaM2) {
               pT = pmom.pT();
               deltaM2 = dm2;
               mass2 = mz2;
             }
           }
         }
         if (pT>0. && mass2 > 0. && inRange(sqrt(mass2)/GeV, 75.0, 105.0)) {
           _eventsFilledZ += weight;
           MSG_DEBUG("Z pmom.pT() = " << pT/GeV << " GeV");
           _h_dsigdpt_z->fill(pT/GeV, weight);
           // return if found a Z
           return;
         }
       }
       // There is no Z -> ee candidate... so this might be a W event
       const LeadingParticlesFinalState& enuFS = applyProjection<LeadingParticlesFinalState>(event, "enuFS");
       const LeadingParticlesFinalState& enubFS = applyProjection<LeadingParticlesFinalState>(event, "enubFS");
 
       double deltaM2=1e30;
       double pT=-1.;
       for(unsigned int iw=0;iw<2;++iw) {
         Particles Wdaughters;
         Wdaughters = iw==0 ? enuFS.particles() : enubFS.particles();
         for(unsigned int ix=0;ix<Wdaughters.size();++ix) {
           for(unsigned int iy=ix+1;iy<Wdaughters.size();++iy) {
             if(Wdaughters[ix].pdgId()==Wdaughters[iy].pdgId())  continue;
             const FourMomentum pmom = Wdaughters[0].momentum() + Wdaughters[1].momentum();
             double dm2 = abs(pmom.mass2()-sqr(80.4*GeV));
             if(dm2<deltaM2) {
               pT = pmom.pT();
               deltaM2 = dm2;
             }
           }
         }
       }
       if(pT>0.) {
         _eventsFilledW += weight;
         _h_dsigdpt_w->fill(pT/GeV, weight);
       }
     }
 
 
 
     void finalize() {
       // Get cross-section per event (i.e. per unit weight) from generator
       const double xSecPerEvent = crossSectionPerEvent()/picobarn;
 
       // Correct W pT distribution to W cross-section
       const double xSecW = xSecPerEvent * _eventsFilledW;
 
       // Correct Z pT distribution to Z cross-section
       const double xSecZ = xSecPerEvent * _eventsFilledZ;
 
       // Get W and Z pT integrals
       const double wpt_integral = integral(_h_dsigdpt_w);
       const double zpt_integral = integral(_h_dsigdpt_z);
 
       // Divide and scale ratio histos
       if (xSecW == 0 || wpt_integral == 0 || xSecZ == 0 || zpt_integral == 0) {
         MSG_WARNING("Not filling ratio plot because input histos are empty");
       } else {
         // Scale factor converts event counts to cross-sections, and inverts the
         // branching ratios since only one decay channel has been analysed for each boson.
         // Oh, and we put MW/MZ in, like they do in the paper.
         const double MW_MZ = 0.8820; // Ratio M_W/M_Z
         const double BRZEE_BRWENU = 0.033632 / 0.1073; // Ratio of branching fractions
         const double scalefactor = (xSecW / wpt_integral) / (xSecZ / zpt_integral) * MW_MZ * BRZEE_BRWENU;
-        for (size_t ibin=0; ibin<_h_dsigdpt_scaled_z->numPoints(); ibin++) {
-          if (_h_dsigdpt_w->bin(ibin).area() == 0 || _h_dsigdpt_z->bin(ibin).area() == 0) {
-            _h_dsigdpt_scaled_z->point(ibin) = Point2D(_h_dsigdpt_w->bin(ibin).midpoint(), 0.,
-                                                       _h_dsigdpt_w->bin(ibin).width(), 0.);
-          } else {
-            double yval = scalefactor * _h_dsigdpt_w->bin(ibin).area() / _h_dsigdpt_z->bin(ibin).area();
-            double dy2 = 0.;
-            // binWidth(ibin) is needed because binHeight is actually sumofweights. It's AIDA. Don't ask.  :-((((
-            dy2 += pow(_h_dsigdpt_w->bin(ibin).areaErr()/_h_dsigdpt_w->bin(ibin).height(),2);
-            dy2 += pow(_h_dsigdpt_z->bin(ibin).areaErr()/_h_dsigdpt_z->bin(ibin).height(),2);
-            double dy = scalefactor * _h_dsigdpt_w->bin(ibin).area()/_h_dsigdpt_z->bin(ibin).area() * sqrt(dy2);
-
-            _h_dsigdpt_scaled_z->point(ibin) = Point2D(_h_dsigdpt_w->bin(ibin).midpoint(), yval,
-                                                       _h_dsigdpt_w->bin(ibin).width(), dy);
+        for (size_t ibin = 0; ibin < _h_dsigdpt_w->numBins(); ibin++) {
+          const double xval = _h_dsigdpt_w->bin(ibin).midpoint();
+          const double xerr = _h_dsigdpt_w->bin(ibin).width() / 2.;
+          double yval(0), yerr(0);
+          if (_h_dsigdpt_w->bin(ibin).sumW() != 0 && _h_dsigdpt_z->bin(ibin).sumW() != 0) {
+            yval = scalefactor * _h_dsigdpt_w->bin(ibin).sumW() / _h_dsigdpt_z->bin(ibin).sumW();
+            yerr = yval * sqrt( sqr(_h_dsigdpt_w->bin(ibin).relErr()) + sqr(_h_dsigdpt_z->bin(ibin).areaErr()) );
           }
+          _h_dsigdpt_scaled_z->addPoint(xval, yval, xerr, yerr);
         }
       }
 
       // Normalize non-ratio histos
       normalize(_h_dsigdpt_w, xSecW);
       normalize(_h_dsigdpt_z, xSecZ);
-
     }
 
 
     //@}
 
   private:
 
     /// @name Event counters for cross section normalizations
     //@{
     double _eventsFilledW;
     double _eventsFilledZ;
     //@}
 
     //@{
     /// Histograms
     Histo1DPtr  _h_dsigdpt_w;
     Histo1DPtr  _h_dsigdpt_z;
     Scatter2DPtr _h_dsigdpt_scaled_z;
     //@}
 
   };
 
 
 
   // The hook for the plugin system
   DECLARE_RIVET_PLUGIN(D0_2001_S4674421);
 
 }