diff --git a/analyses/pluginALICE/ALICE_2010_I880049.cc b/analyses/pluginALICE/ALICE_2010_I880049.cc
--- a/analyses/pluginALICE/ALICE_2010_I880049.cc
+++ b/analyses/pluginALICE/ALICE_2010_I880049.cc
@@ -1,108 +1,108 @@
 // -*- C++ -*-
 #include "Rivet/Analysis.hh"
 #include "Rivet/Projections/ChargedFinalState.hh"
 #include "Rivet/Tools/Cuts.hh"
 #include "Rivet/Projections/SingleValueProjection.hh"
 #include "Rivet/Tools/AliceCommon.hh"
 #include "Rivet/Projections/AliceCommon.hh"
 #include "Rivet/Projections/HepMCHeavyIon.hh"
 
 namespace Rivet {
 
   /// @brief ALICE PbPb at 2.76 TeV multiplicity at mid-rapidity
   class ALICE_2010_I880049 : public Analysis {    
   public:
 
     /// Constructor
     DEFAULT_RIVET_ANALYSIS_CTOR(ALICE_2010_I880049);
 
     /// @name Analysis methods
     //@{
 
     /// Book histograms and initialise projections before the run
     void init() {
 
       // Declare centrality projection
       declareCentrality(ALICE::V0MMultiplicity(),
         "ALICE_2015_PBPBCentrality", "V0M", "V0M");
 
       // Trigger projections
       declare(ChargedFinalState((Cuts::eta > 2.8 && Cuts::eta < 5.1) &&
         Cuts::pT > 0.1*GeV), "VZERO1");
       declare(ChargedFinalState((Cuts::eta > -3.7 && Cuts::eta < -1.7) &&
         Cuts::pT > 0.1*GeV), "VZERO2");
       declare(ChargedFinalState(Cuts::abseta < 1. && Cuts::pT > 0.15*GeV),
         "SPD");
 
       // Charged, primary particles with |eta| < 0.5 and pT > 50 MeV
       declare(ALICE::PrimaryParticles(Cuts::abseta < 0.5 &&
         Cuts::pT > 50*MeV && Cuts::abscharge > 0), "APRIM");
 
       // Access the HepMC heavy ion info
       declare(HepMCHeavyIon(), "HepMC");
 
       // Histograms and variables initialization
-      _histNchVsCentr = bookProfile1D(1, 1, 1);
-      _histNpartVsCentr = bookProfile1D(1, 1, 2);
+      book(_histNchVsCentr, 1, 1, 1);
+      book(_histNpartVsCentr, 1, 1, 2);
 
     }
 
 
     /// Perform the per-event analysis
     void analyze(const Event& event) {
 
       // Charged, primary particles with at least pT = 50 MeV
       // in eta range of |eta| < 0.5
       Particles chargedParticles =
         applyProjection<ALICE::PrimaryParticles>(event,"APRIM").particles();
 
       // Trigger projections
       const ChargedFinalState& vz1 =
         applyProjection<ChargedFinalState>(event,"VZERO1");
       const ChargedFinalState& vz2 =
         applyProjection<ChargedFinalState>(event,"VZERO2");
       const ChargedFinalState& spd =
         applyProjection<ChargedFinalState>(event,"SPD");
       int fwdTrig = (vz1.particles().size() > 0 ? 1 : 0);
       int bwdTrig = (vz2.particles().size() > 0 ? 1 : 0);
       int cTrig = (spd.particles().size() > 0 ? 1 : 0);
 
       if (fwdTrig + bwdTrig + cTrig < 2) vetoEvent;
 
       const CentralityProjection& centrProj =
         apply<CentralityProjection>(event, "V0M");
       double centr = centrProj();
       if (centr > 80) vetoEvent;
       // Calculate number of charged particles and fill histogram
       double nch = chargedParticles.size();
       _histNchVsCentr->fill(centr, nch);
 
       // Attempt to extract Npart form GenEvent.
       if (event.genEvent()->heavy_ion()) {
         const HepMCHeavyIon & hi = apply<HepMCHeavyIon>(event, "HepMC");
         _histNpartVsCentr->fill(centr, hi.Npart_proj() + hi.Npart_targ());
       }
     }
 
     
     /// Normalise histograms etc., after the run
     //void finalize() {   }
 
     //@}
 
 
   private:
 
     /// @name Histograms
     //@{
     Profile1DPtr _histNchVsCentr;
     Profile1DPtr _histNpartVsCentr;
     //@}
 
   };
 
 
   // The hook for the plugin system
   DECLARE_RIVET_PLUGIN(ALICE_2010_I880049);
 
 }
diff --git a/analyses/pluginALICE/ALICE_2012_I1126966.cc b/analyses/pluginALICE/ALICE_2012_I1126966.cc
--- a/analyses/pluginALICE/ALICE_2012_I1126966.cc
+++ b/analyses/pluginALICE/ALICE_2012_I1126966.cc
@@ -1,146 +1,146 @@
 //-*- C++ -*-
 #include "Rivet/Analysis.hh"
 #include "Rivet/Projections/CentralityProjection.hh"
 #include "Rivet/Projections/AliceCommon.hh"
 #include "Rivet/Tools/AliceCommon.hh"
 
 namespace Rivet {
 
 
   /// Pion, Kaon, and Proton Production in 0-5%
   ///  central Pb--Pb Collisions at 2.76 TeV
   class ALICE_2012_I1126966 : public Analysis {
   public:
 
     /// Constructor
     DEFAULT_RIVET_ANALYSIS_CTOR(ALICE_2012_I1126966);
 
     /// Book histograms and initialise projections before the run
     void init() {
       // Particles of interest.
       declare(ALICE::PrimaryParticles(Cuts::absrap < 0.5),"CFS");
 
       // The event trigger.
       declare(ALICE::V0AndTrigger(), "V0-AND");
       // The centrality projection.
       declareCentrality(ALICE::V0MMultiplicity(),
            "ALICE_2015_PBPBCentrality", "V0M", "V0M");
 
       // Invariant pT distributions.
       book(_histPtPi, "d01-x01-y01"); //pi+
       book(_histPtPibar, "d01-x01-y02");// pi-
       book(_histPtKaon, "d02-x01-y01"); //K+
       book(_histPtKaonbar, "d02-x01-y02"); //K-
       book(_histPtProton, "d03-x01-y01"); //P+
       book(_histPtProtonbar, "d03-x01-y02"); //P-
       // Yield histograms.
       book(_histNpi, "d04-x01-y01");
       book(_histNpibar, "d04-x01-y02");
       book(_histNKaon, "d04-x01-y03");
       book(_histNKaonbar, "d04-x01-y04");
       book(_histNproton, "d04-x01-y05");
       book(_histNprotonbar, "d04-x01-y06");
       // Sum of weights of triggered events.
       book(sow, "sow");
     }
 
 
     /// Perform the per-event analysis
     void analyze(const Event& event) {
       // Analysis only considers 0-5% central events
       if (apply<CentralityProjection>(event,"V0M")() > 5.0)
         vetoEvent;
       // Event trigger.
       if (!apply<ALICE::V0AndTrigger>(event, "V0-AND")() ) vetoEvent;
 
       sow->fill();
       // ID particles counters for this event.
       int Npi=0;
       int Npibar=0;
       int NKaon=0;
       int NKaonbar=0;
       int Nproton=0;
       int Nprotonbar=0;
 
       for (const Particle& p : apply<ALICE::PrimaryParticles>(event,"CFS").particles()) {
-          const double pWeight = weight / p.pT() / 2. / M_PI;
+          const double pWeight = 1.0 / p.pT() / 2. / M_PI;
           switch (p.pid()) {
             case 211: // pi+
 	      Npi++;
               _histPtPi->fill(p.pT()/GeV,  pWeight);
               break;
 	    case -211: //pi-
 	      Npibar++;
 	      _histPtPibar->fill(p.pT()/GeV, pWeight);
               break;
             case 2212: // proton
 	      Nproton++;
               _histPtProton->fill(p.pT()/GeV, pWeight);
 	      break;
 	    case -2212: // p-bar
 	      Nprotonbar++;
               _histPtProtonbar->fill(p.pT()/GeV, pWeight);
               break;
             case 321: // K+
 	      NKaon++;
               _histPtKaon->fill(p.pT()/GeV,  pWeight);
 	      break;
 	    case -321: // K-
 	      NKaonbar++;
               _histPtKaonbar->fill(p.pT()/GeV,  pWeight);
              break;
         }
       } // Particle loop ends.
 
       // Fill yield histograms.
       _histNpi->fill(0.0, Npi);
       _histNpibar->fill(0.0, Npibar);
       _histNKaon->fill(0.0, NKaon);
       _histNKaonbar->fill(0.0, NKaonbar);
       _histNproton->fill(0.0, Nproton);
       _histNprotonbar->fill(0.0, Nprotonbar);
     }
 
 
     void finalize() {
        const double s = 1./sow->sumW();
        _histPtPi->scaleW(s);
        _histPtPibar->scaleW(s);
        _histPtKaon->scaleW(s);
        _histPtKaonbar->scaleW(s);
        _histPtProton->scaleW(s);
        _histPtProtonbar->scaleW(s);
        _histNpi->scaleW(s);
        _histNpibar->scaleW(s);
        _histNKaon->scaleW(s);
        _histNKaonbar->scaleW(s);
        _histNproton->scaleW(s);
        _histNprotonbar->scaleW(s);
 
 }
 
   private:
 
       // pT histograms
     Histo1DPtr _histPtPi;
     Histo1DPtr _histPtKaon;
     Histo1DPtr _histPtProton;
     Histo1DPtr _histPtPibar;
     Histo1DPtr _histPtKaonbar;
     Histo1DPtr _histPtProtonbar;
     Histo1DPtr _histNpi;
     Histo1DPtr _histNpibar;
     Histo1DPtr _histNKaon;
     Histo1DPtr _histNKaonbar;
     Histo1DPtr _histNproton;
     Histo1DPtr _histNprotonbar;
     CounterPtr sow;
 
   };
 
 
     // The hook for the plugin system
   DECLARE_RIVET_PLUGIN(ALICE_2012_I1126966);
 
 
 }
diff --git a/analyses/pluginALICE/ALICE_2012_I1127497.cc b/analyses/pluginALICE/ALICE_2012_I1127497.cc
--- a/analyses/pluginALICE/ALICE_2012_I1127497.cc
+++ b/analyses/pluginALICE/ALICE_2012_I1127497.cc
@@ -1,215 +1,215 @@
 // -*- C++ -*-
 #include "Rivet/Analysis.hh"
 #include "Rivet/Projections/ChargedFinalState.hh"
 #include "Rivet/Tools/Cuts.hh"
 #include "Rivet/Projections/SingleValueProjection.hh"
 #include "Rivet/Tools/AliceCommon.hh"
 #include "Rivet/Projections/AliceCommon.hh"
 #include "Rivet/Projections/HepMCHeavyIon.hh"
 
 namespace Rivet {
 
   /// @brief ALICE PbPb at 2.76 TeV R_AA analysis.
   class ALICE_2012_I1127497 : public Analysis {
   public:
 
     /// Constructor
     DEFAULT_RIVET_ANALYSIS_CTOR(ALICE_2012_I1127497);
 
 
     /// @name Analysis methods
     //@{
 
     /// Book histograms and initialise projections before the run
     void init() {
 
       // Access the HepMC heavy ion info
       declare(HepMCHeavyIon(), "HepMC");
 
       // Declare centrality projection
       declareCentrality(ALICE::V0MMultiplicity(),
         "ALICE_2015_PBPBCentrality", "V0M", "V0M");
 
       // Charged, primary particles with |eta| < 0.5 and pT > 150 MeV
       declare(ALICE::PrimaryParticles(Cuts::abseta < 0.5 &&
         Cuts::pT > 150*MeV && Cuts::abscharge > 0), "APRIM");
 
       // Loop over all histograms
       for (size_t ihist = 0; ihist < NHISTOS; ++ihist) {
 
         // Initialize PbPb objects
         book(_histNch[PBPB][ihist], ihist+1, 1, 1);
 
         std::string nameCounterPbPb = "counter.pbpb." + std::to_string(ihist);
         book(_counterSOW[PBPB][ihist], nameCounterPbPb,
           "Sum of weights counter for PbPb");
 
         std::string nameCounterNcoll = "counter.ncoll." + std::to_string(ihist);
         book(_counterNcoll[ihist], nameCounterNcoll,
           "Ncoll counter for PbPb");
 
         // Initialize pp objects. In principle, only one pp histogram would be
         // needed since centrality does not make any difference here. However,
         // in some cases in this analysis the binning differ from each other,
         // so this is easy-to-implement way to account for that.
         std::string namePP = _histNch[PBPB][ihist]->name() + "-pp";
         // The binning is taken from the reference data
         book(_histNch[PP][ihist], namePP, refData(ihist+1, 1, 1));
 
         std::string nameCounterpp = "counter.pp." + std::to_string(ihist);
         book(_counterSOW[PP][ihist], nameCounterpp,
           "Sum of weights counter for pp");
 
         // Book ratios, to be used in finalize
-        _histRAA[ihist] = bookScatter2D(ihist+16, 1, 1);
+        book(_histRAA[ihist], ihist+16, 1, 1);
       }
 
       // Centrality regions keeping boundaries for a certain region.
       // Note, that some regions overlap with other regions.
       _centrRegions.clear();
       _centrRegions = {{0., 5.},   {5., 10.},  {10., 20.},
                        {20., 30.}, {30., 40.}, {40., 50.},
                        {50., 60.}, {60., 70.}, {70., 80.},
                        {0., 10.},  {0., 20.},  {20., 40.},
                        {40., 60.}, {40., 80.}, {60., 80.}};
 
       // Find out the beam type, also specified from option.
       string beamOpt = getOption<string>("beam","NONE");
       if (beamOpt != "NONE") {
         MSG_WARNING("You are using a specified beam type, instead of using what"
 	"is provided by the generator. "
 	"Only do this if you are completely sure what you are doing.");
 	if (beamOpt=="PP") isHI = false;
 	else if (beamOpt=="HI") isHI = true;
 	else {
 	  MSG_ERROR("Beam error (option)!");
 	  return;
       	}
       }
       else {
         const ParticlePair& beam = beams();
         if (beam.first.pid() == PID::PROTON && beam.second.pid() == PID::PROTON) isHI = false;
 	else if (beam.first.pid() == 1000822080 && beam.second.pid() == 1000822080)
 	  isHI = true;
 	else {
 	  MSG_ERROR("Beam error (found)!");
 	  return;
 	}
       }
     }
 
     /// Perform the per-event analysis
     void analyze(const Event& event) {
 
       // Charged, primary particles with at least pT = 150 MeV
       // in eta range of |eta| < 0.5
       Particles chargedParticles =
         apply<ALICE::PrimaryParticles>(event,"APRIM").particlesByPt();
 
       // Check type of event.
       if ( isHI ) {
 
         const HepMCHeavyIon & hi = apply<HepMCHeavyIon>(event, "HepMC");
 
         // Prepare centrality projection and value
         const CentralityProjection& centrProj =
           apply<CentralityProjection>(event, "V0M");
         double centr = centrProj();
         // Veto event for too large centralities since those are not used
         // in the analysis at all
         if ((centr < 0.) || (centr > 80.)) vetoEvent;
 
         // Fill PbPb histograms and add weights based on centrality value
         for (size_t ihist = 0; ihist < NHISTOS; ++ihist) {
           if (inRange(centr, _centrRegions[ihist].first, _centrRegions[ihist].second)) {
             _counterSOW[PBPB][ihist]->fill();
             _counterNcoll[ihist]->fill(hi.Ncoll());
             for (const Particle& p : chargedParticles) {
               double pT = p.pT()/GeV;
               if (pT < 50.) {
                 const double pTAtBinCenter = _histNch[PBPB][ihist]->binAt(pT).xMid();
                 _histNch[PBPB][ihist]->fill(pT, 1/pTAtBinCenter);
               }
             }
           }
         }
 
       }
       else {
 
         // Fill all pp histograms and add weights
         for (size_t ihist = 0; ihist < NHISTOS; ++ihist) {
           _counterSOW[PP][ihist]->fill();
           for (const Particle& p : chargedParticles) {
             double pT = p.pT()/GeV;
             if (pT < 50.) {
               const double pTAtBinCenter = _histNch[PP][ihist]->binAt(pT).xMid();
               _histNch[PP][ihist]->fill(pT, 1/pTAtBinCenter);
             }
           }
         }
 
       }
 
     }
 
 
     /// Normalise histograms etc., after the run
     void finalize() {
 
       // Right scaling of the histograms with their individual weights.
       for (size_t itype = 0; itype < EVENT_TYPES; ++itype ) {
         for (size_t ihist = 0; ihist < NHISTOS; ++ihist) {
           if (_counterSOW[itype][ihist]->sumW() > 0.) {
             scale(_histNch[itype][ihist],
               (1. / _counterSOW[itype][ihist]->sumW() / 2. / M_PI));
           }
         }
       }
 
       // Postprocessing of the histograms
       for (size_t ihist = 0; ihist < NHISTOS; ++ihist) {
         // If there are entires in histograms for both beam types
         if (_histNch[PP][ihist]->numEntries() > 0 && _histNch[PBPB][ihist]->numEntries() > 0) {
           // Initialize and fill R_AA histograms
           divide(_histNch[PBPB][ihist], _histNch[PP][ihist], _histRAA[ihist]);
           // Scale by Ncoll. Unfortunately some generators does not provide
           // Ncoll value (eg. JEWEL), so the following scaling will be done
           // only if there are entries in the counters
           double ncoll = _counterNcoll[ihist]->sumW();
           double sow = _counterSOW[PBPB][ihist]->sumW();
           if (ncoll > 1e-6 && sow > 1e-6)
             _histRAA[ihist]->scaleY(1. / (ncoll / sow));
 
         }
       }
 
     }
 
     //@}
 
   private:
 
     bool isHI;
     static const int NHISTOS = 15;
     static const int EVENT_TYPES = 2;
     static const int PP = 0;
     static const int PBPB = 1;
 
     /// @name Histograms
     //@{
     Histo1DPtr _histNch[EVENT_TYPES][NHISTOS];
     CounterPtr _counterSOW[EVENT_TYPES][NHISTOS];
     CounterPtr _counterNcoll[NHISTOS];
     Scatter2DPtr _histRAA[NHISTOS];
     //@}
 
     std::vector<std::pair<double, double>> _centrRegions;
 
   };
 
   // The hook for the plugin system
   DECLARE_RIVET_PLUGIN(ALICE_2012_I1127497);
 
 
 }
diff --git a/analyses/pluginALICE/ALICE_2012_I930312.cc b/analyses/pluginALICE/ALICE_2012_I930312.cc
--- a/analyses/pluginALICE/ALICE_2012_I930312.cc
+++ b/analyses/pluginALICE/ALICE_2012_I930312.cc
@@ -1,343 +1,342 @@
 // -*- C++ -*-
 #include "Rivet/Analysis.hh"
 #include "Rivet/Projections/ChargedFinalState.hh"
 #include "Rivet/Projections/SingleValueProjection.hh"
 #include "Rivet/Tools/AliceCommon.hh"
 #include "Rivet/Projections/AliceCommon.hh"
 
 namespace Rivet {
 
   /// @brief ALICE PbPb at 2.76 TeV azimuthal di-hadron correlations
   class ALICE_2012_I930312 : public Analysis {
   public:
 
     // Constructor
     DEFAULT_RIVET_ANALYSIS_CTOR(ALICE_2012_I930312);
 
 
     /// @name Analysis methods
     //@{
 
     /// Book histograms and initialise projections before the run
     void init() {
 
       // Declare centrality projection
       declareCentrality(ALICE::V0MMultiplicity(),
         "ALICE_2015_PBPBCentrality", "V0M", "V0M");
 
       // Projection for trigger particles: charged, primary particles
       // with |eta| < 1.0 and 8 < pT < 15 GeV/c
       declare(ALICE::PrimaryParticles(Cuts::abseta < 1.0 && Cuts::abscharge > 0
         && Cuts::ptIn(8.*GeV, 15.*GeV)), "APRIMTrig");
 
       // pT bins edges
       vector<double> ptBins = { 3., 4., 6., 8., 10. };
 
       // Projections for associated particles: charged, primary particles
       // with |eta| < 1.0 and different pT bins
       for (int ipt = 0; ipt < PT_BINS; ++ipt) {
         Cut cut = Cuts::abseta < 1.0 && Cuts::abscharge > 0 &&
           Cuts::ptIn(ptBins[ipt]*GeV, ptBins[ipt+1]*GeV);
         declare(ALICE::PrimaryParticles(cut), "APRIMAssoc" + toString(ipt));
       }
 
       // Create event strings
       vector<string> evString = { "pp", "central", "peripheral" };
 
       // Initialize trigger counters and yield histograms
       string title = "Per trigger particle yield";
       string xtitle = "$\\Delta\\eta$ (rad)";
       string ytitle =
         "$1 / N_{trig} {\\rm d}N_{assoc} / {\\rm d}\\Delta\\eta$ (rad$^-1$)";
       for (int itype = 0; itype < EVENT_TYPES; ++itype) {
-        _counterTrigger[itype] = bookCounter("counter." + toString(itype));
+        book(_counterTrigger[itype], "counter." + toString(itype));
         for (int ipt = 0; ipt < PT_BINS; ++ipt) {
           string name = "yield." + evString[itype] + ".pt" + toString(ipt);
           book(_histYield[itype][ipt], name, 36,
             -0.5*M_PI, 1.5*M_PI, title, xtitle, ytitle);
         }
       }
 
       // Find out the beam type, also specified from option.
       string beamOpt = getOption<string>("beam","NONE");
       if (beamOpt != "NONE") {
         MSG_WARNING("You are using a specified beam type, instead of using what"
 	"is provided by the generator. "
 	"Only do this if you are completely sure what you are doing.");
 	if (beamOpt=="PP") isHI = false;
 	else if (beamOpt=="HI") isHI = true;
 	else {
 	  MSG_ERROR("Beam error (option)!");
 	  return;
       	}
       }
       else {
         const ParticlePair& beam = beams();
         if (beam.first.pid() == 2212 && beam.second.pid() == 2212) isHI = false;
 	else if (beam.first.pid() == 1000822080 && beam.second.pid() == 1000822080)
 	  isHI = true;
 	else {
 	  MSG_ERROR("Beam error (found)!");
 	  return;
 	}
       }
 
       // Initialize IAA and ICP histograms
-      _histIAA[0] = bookScatter2D(1, 1, 1);
-      _histIAA[1] = bookScatter2D(2, 1, 1);
-      _histIAA[2] = bookScatter2D(5, 1, 1);
-      _histIAA[3] = bookScatter2D(3, 1, 1);
-      _histIAA[4] = bookScatter2D(4, 1, 1);
-      _histIAA[5] = bookScatter2D(6, 1, 1);
+      book(_histIAA[0], 1, 1, 1);
+      book(_histIAA[1], 2, 1, 1);
+      book(_histIAA[2], 5, 1, 1);
+      book(_histIAA[3], 3, 1, 1);
+      book(_histIAA[4], 4, 1, 1);
+      book(_histIAA[5], 6, 1, 1);
 
       // Initialize background-subtracted yield histograms
       for (int itype = 0; itype < EVENT_TYPES; ++itype) {
         for (int ipt = 0; ipt < PT_BINS; ++ipt) {
           string newname = _histYield[itype][ipt]->name() + ".nobkg";
           string newtitle = _histYield[itype][ipt]->title() +
             ", background subtracted";
-          _histYieldNoBkg[itype][ipt] =
-            bookHisto1D(newname, 36, -0.5*M_PI, 1.5*M_PI, newtitle,
-            _histYield[itype][ipt]->annotation("XLabel"),
-            _histYield[itype][ipt]->annotation("YLabel"));
+          book(_histYieldNoBkg[itype][ipt], newname, 36, -0.5*M_PI, 1.5*M_PI, newtitle,
+               _histYield[itype][ipt]->annotation("XLabel"),
+               _histYield[itype][ipt]->annotation("YLabel"));
         }
       }
 
     }
 
 
     /// Perform the per-event analysis
     void analyze(const Event& event) {
 
       // Trigger particles
       Particles trigParticles =
         applyProjection<ALICE::PrimaryParticles>(event,"APRIMTrig").particles();
 
       // Associated particles
       Particles assocParticles[PT_BINS];
       for (int ipt = 0; ipt < PT_BINS; ++ipt) {
         string pname = "APRIMAssoc" + toString(ipt);
         assocParticles[ipt] =
           applyProjection<ALICE::PrimaryParticles>(event,pname).particles();
       }
 
       // Check type of event. This may not be a perfect way to check for the
       // type of event as there might be some weird conditions hidden inside.
       // For example some HepMC versions check if number of hard collisions
       // is equal to 0 and assign 'false' in that case, which is usually wrong.
       // This might be changed in the future
       int ev_type = 0; // pp
       if ( isHI ) {
         // Prepare centrality projection and value
         const CentralityProjection& centrProj =
           apply<CentralityProjection>(event, "V0M");
         double centr = centrProj();
         // Set the flag for the type of the event
         if (centr > 0.0 && centr < 5.0)
           ev_type = 1; // PbPb, central
         else if (centr > 60.0 && centr < 90.0)
           ev_type = 2; // PbPb, peripherial
         else
           vetoEvent; // PbPb, other, this is not used in the analysis at all
       }
 
       // Fill trigger histogram for a proper event type
       _counterTrigger[ev_type]->fill(trigParticles.size());
 
       // Loop over trigger particles
       for (const Particle& trigParticle : trigParticles) {
         // For each pt bin
         for (int ipt = 0; ipt < PT_BINS; ++ipt) {
           // Loop over associated particles
           for (const Particle& assocParticle : assocParticles[ipt]) {
             // If associated and trigger particle are not the same particles.
             if (!isSame(trigParticle, assocParticle)) {
               // Test trigger particle.
               if (trigParticle.pt() > assocParticle.pt()) {
                 // Calculate delta phi in range (-0.5*PI, 1.5*PI).
                 double dPhi = deltaPhi(trigParticle, assocParticle, true);
                 if (dPhi < -0.5 * M_PI) dPhi += 2 * M_PI;
                 // Fill yield histogram for calculated delta phi
                 _histYield[ev_type][ipt]->fill(dPhi);
               }
             }
           }
         }
       }
     }
 
 
     /// Normalise histograms etc., after the run
     void finalize() {
 
       // Check for the reentrant finalize
       bool pp_available = false, PbPb_available = false;
       for (int itype = 0; itype < EVENT_TYPES; ++itype) {
         for (int ipt = 0; ipt < PT_BINS; ++ipt) {
           if (_histYield[itype][ipt]->numEntries() > 0)
             itype == 0 ? pp_available = true : PbPb_available = true;
         }
       }
       // Skip postprocessing if pp or PbPb histograms are not available
       if (!(pp_available && PbPb_available))
         return;
 
       // Variable for near and away side peak integral calculation
       double integral[EVENT_TYPES][PT_BINS][2] = { { {0.0} } };
 
       // Variables for background calculation
       double bkg = 0.0;
       double bkgErr[EVENT_TYPES][PT_BINS] = { {0.0} };
 
       // Variables for integration error calculation
       double norm[EVENT_TYPES] = {0.0};
       double numEntries[EVENT_TYPES][PT_BINS][2] = { { {0.0} } };
       int numBins[EVENT_TYPES][PT_BINS][2] = { { {0} } };
 
       // For each event type
       for (int itype = 0; itype < EVENT_TYPES; ++itype) {
         // Get counter
         CounterPtr counter = _counterTrigger[itype];
         // For each pT range
         for (int ipt = 0; ipt < PT_BINS; ++ipt) {
 
           // Get yield histograms
           Histo1DPtr hYield = _histYield[itype][ipt];
           Histo1DPtr hYieldNoBkg = _histYieldNoBkg[itype][ipt];
 
           // Check if histograms are fine
           if (counter->sumW() == 0 || hYield->numEntries() == 0) {
             MSG_WARNING("There are no entries in one of the histograms");
             continue;
           }
 
           // Scale yield histogram
           norm[itype] = 1. / counter->sumW();
           scale(hYield, norm[itype]);
 
           // Calculate background
           double sum = 0.0;
           int nbins = 0;
           for (size_t ibin = 0; ibin < hYield->numBins(); ++ibin) {
             double xmid = hYield->bin(ibin).xMid();
             if (inRange(xmid, -0.5 * M_PI, -0.5 * M_PI + 0.4) ||
                 inRange(xmid, 0.5 * M_PI - 0.4, 0.5 * M_PI + 0.4) ||
                 inRange(xmid, 1.5 * M_PI - 0.4, 1.5 * M_PI)) {
               sum += hYield->bin(ibin).sumW();
               nbins += 1;
             }
           }
           if (nbins == 0) {
             MSG_WARNING("Failed to estimate background!");
             continue;
           }
           bkg = sum / nbins;
 
           // Calculate background error
           sum = 0.0;
           nbins = 0;
           for (size_t ibin = 0; ibin < hYield->numBins(); ++ibin) {
             double xmid = hYield->bin(ibin).xMid();
             if (inRange(xmid, 0.5 * M_PI - 0.4, 0.5 * M_PI + 0.4)) {
               sum += (hYield->bin(ibin).sumW() - bkg) *
                      (hYield->bin(ibin).sumW() - bkg);
               nbins++;
             }
           }
           if (nbins < 2) {
             MSG_WARNING("Failed to estimate background error!");
             continue;
           }
           bkgErr[itype][ipt] = sqrt(sum / (nbins - 1));
 
           // Fill histograms with removed background
           for (size_t ibin = 0; ibin < hYield->numBins(); ++ibin) {
             hYieldNoBkg->fillBin(ibin, hYield->bin(ibin).sumW() - bkg);
           }
 
           // Integrate near-side yield
           size_t lowerBin = hYield->binIndexAt(-0.7 + 0.02);
           size_t upperBin = hYield->binIndexAt( 0.7 - 0.02) + 1;
           nbins = upperBin - lowerBin;
           numBins[itype][ipt][NEAR] = nbins;
           integral[itype][ipt][NEAR] =
             hYield->integralRange(lowerBin, upperBin) - nbins * bkg;
           numEntries[itype][ipt][NEAR] =
             hYield->integralRange(lowerBin, upperBin) * counter->sumW();
 
           // Integrate away-side yield
           lowerBin = hYield->binIndexAt(M_PI - 0.7 + 0.02);
           upperBin = hYield->binIndexAt(M_PI + 0.7 - 0.02) + 1;
           nbins = upperBin - lowerBin;
           numBins[itype][ipt][AWAY] = nbins;
           integral[itype][ipt][AWAY] =
             hYield->integralRange(lowerBin, upperBin) - nbins * bkg;
           numEntries[itype][ipt][AWAY] =
             hYield->integralRange(lowerBin, upperBin) * counter->sumW();
 
         }
       }
 
       // Variables for IAA/ICP plots
       double yval[2] = { 0.0, 0.0 };
       double yerr[2] = { 0.0, 0.0 };
       double xval[PT_BINS] = { 3.5, 5.0, 7.0, 9.0 };
       double xerr[PT_BINS] = { 0.5, 1.0, 1.0, 1.0 };
 
       int types1[3] = {1, 2, 1};
       int types2[3] = {0, 0, 2};
 
       // Fill IAA/ICP plots for near and away side peak
       for (int ihist = 0; ihist < 3; ++ihist) {
         int type1 = types1[ihist];
         int type2 = types2[ihist];
         double norm1 = norm[type1];
         double norm2 = norm[type2];
         for (int ipt = 0; ipt < PT_BINS; ++ipt) {
           double bkgErr1 = bkgErr[type1][ipt];
           double bkgErr2 = bkgErr[type2][ipt];
           for (int ina = 0; ina < 2; ++ina) {
             double integ1 = integral[type1][ipt][ina];
             double integ2 = integral[type2][ipt][ina];
             double numEntries1 = numEntries[type1][ipt][ina];
             double numEntries2 = numEntries[type2][ipt][ina];
             double numBins1 = numBins[type1][ipt][ina];
             double numBins2 = numBins[type2][ipt][ina];
             yval[ina] = integ1 / integ2;
             yerr[ina] = norm1 * norm1 * numEntries1 +
               norm2 * norm2 * numEntries2 * integ1 * integ1 / (integ2 * integ2) +
               numBins1 * numBins1 * bkgErr1 * bkgErr1 +
               numBins2 * numBins2 * bkgErr2 * bkgErr2 * integ1 * integ1 / (integ2 * integ2);
             yerr[ina] = sqrt(yerr[ina])/integ2;
           }
           _histIAA[ihist]->addPoint(xval[ipt], yval[NEAR], xerr[ipt], yerr[NEAR]);
           _histIAA[ihist + 3]->addPoint(xval[ipt], yval[AWAY], xerr[ipt], yerr[AWAY]);
         }
       }
 
     }
 
     //@}
 
   private:
 
     bool isHI;
     static const int PT_BINS = 4;
     static const int EVENT_TYPES = 3;
     static const int NEAR = 0;
     static const int AWAY = 1;
 
     /// @name Histograms
     //@{
     Histo1DPtr _histYield[EVENT_TYPES][PT_BINS];
     Histo1DPtr _histYieldNoBkg[EVENT_TYPES][PT_BINS];
     CounterPtr _counterTrigger[EVENT_TYPES];
     Scatter2DPtr _histIAA[6];
     //@}
 
   };
 
   // The hook for the plugin system
   DECLARE_RIVET_PLUGIN(ALICE_2012_I930312);
 
 }
diff --git a/analyses/pluginALICE/ALICE_2015_PBPBCentrality.cc b/analyses/pluginALICE/ALICE_2015_PBPBCentrality.cc
--- a/analyses/pluginALICE/ALICE_2015_PBPBCentrality.cc
+++ b/analyses/pluginALICE/ALICE_2015_PBPBCentrality.cc
@@ -1,65 +1,66 @@
 #include <Rivet/Analysis.hh>
 #include <Rivet/Projections/AliceCommon.hh>
+#include <Rivet/Projections/HepMCHeavyIon.hh>
 
 namespace Rivet {
 
   /// Dummy analysis for centrality calibration in Pb-Pb at 5.02TeV
   ///
   /// @author Christian Holm Christensen <cholm@nbi.dk>
   class ALICE_2015_PBPBCentrality : public Analysis {
   public:
 
     /// Constructor 
     ALICE_2015_PBPBCentrality()
       : Analysis("ALICE_2015_PBPBCentrality")
     {    }
 
     /// Initialize this analysis. 
     void init() {
       ALICE::V0AndTrigger v0and;
       declare<ALICE::V0AndTrigger>(v0and,"V0-AND");
 
       ALICE::V0MMultiplicity v0m;
       declare<ALICE::V0MMultiplicity>(v0m,"V0M");
 
        // Access the HepMC heavy ion info
       declare(HepMCHeavyIon(), "HepMC");
 
       book(_v0m, "V0M","Forward multiplicity","V0M","Events");
       book(_imp, "V0M_IMP",100,0,20, "Impact parameter","b (fm)","Events");
     }
 
 
     /// Analyse a single event.
     void analyze(const Event& event) {
       // Get and fill in the impact parameter value if the information is valid.
-      _imp->fill(apply<HepMCHeavyIon>(event, "HepMC").impact_parameter(), event.weight());
+      _imp->fill(apply<HepMCHeavyIon>(event, "HepMC").impact_parameter());
 	  
       // Check if we have any hit in either V0-A or -C.  If not, the
       // event is not selected and we get out.
       if (!apply<ALICE::V0AndTrigger>(event,"V0-AND")()) return;
 
       // Fill in the V0 multiplicity for this event
       _v0m->fill(apply<ALICE::V0MMultiplicity>(event,"V0M")());
     }
 
 
     /// Finalize this analysis
     void finalize() {
       _v0m->normalize();
       _imp->normalize();
     }
 
     /// The distribution of V0M multiplicity
     Histo1DPtr _v0m;
     /// The distribution of impact parameters
     Histo1DPtr _imp;
 
   };
 
 
   // The hook for the plugin system
   DECLARE_RIVET_PLUGIN(ALICE_2015_PBPBCentrality);
 
 }
 
diff --git a/analyses/pluginATLAS/ATLAS_2011_S9035664.cc b/analyses/pluginATLAS/ATLAS_2011_S9035664.cc
--- a/analyses/pluginATLAS/ATLAS_2011_S9035664.cc
+++ b/analyses/pluginATLAS/ATLAS_2011_S9035664.cc
@@ -1,134 +1,134 @@
 // -*- C++ -*-
 #include "Rivet/Analysis.hh"
 #include "Rivet/Projections/Beam.hh"
 #include "Rivet/Projections/FinalState.hh"
 #include "Rivet/Projections/ChargedFinalState.hh"
 #include "Rivet/Projections/UnstableParticles.hh"
 
 namespace Rivet {
 
 
   /// @brief  J/psi production at ATLAS
   class ATLAS_2011_S9035664: public Analysis {
   public:
 
     /// Constructor
     ATLAS_2011_S9035664()
       : Analysis("ATLAS_2011_S9035664")
     {}
 
 
     /// @name Analysis methods
     //@{
 
     void init() {
       declare(UnstableParticles(), "UFS");
       book(_nonPrRapHigh    , 14, 1, 1);
       book(_nonPrRapMedHigh , 13, 1, 1);
       book(_nonPrRapMedLow  , 12, 1, 1);
       book(_nonPrRapLow     , 11, 1, 1);
       book(_PrRapHigh       , 18, 1, 1);
       book(_PrRapMedHigh    , 17, 1, 1);
       book(_PrRapMedLow     , 16, 1, 1);
       book(_PrRapLow        , 15, 1, 1);
       book(_IncRapHigh      , 20, 1, 1);
       book(_IncRapMedHigh   , 21, 1, 1);
       book(_IncRapMedLow    , 22, 1, 1);
       book(_IncRapLow       , 23, 1, 1);
     }
 
 
     void analyze(const Event& e) {
 
       // Final state of unstable particles to get particle spectra
       const UnstableParticles& ufs = apply<UnstableFinalState>(e, "UFS");
 
-      foreach (const Particle& p, ufs.particles()) {
+      for (const Particle& p : ufs.particles()) {
         if (p.abspid() != 443) continue;
         ConstGenVertexPtr gv = p.genParticle()->production_vertex();
         bool nonPrompt = false;
         if (gv) {
           for (ConstGenParticlePtr pi: HepMCUtils::particles(gv, Relatives::ANCESTORS)) {
             const PdgId pid2 = pi->pdg_id();
             if (PID::isHadron(pid2) && PID::hasBottom(pid2)) {
               nonPrompt = true;
               break;
             }
           }
         }
         double absrap = p.absrap();
         double xp = p.perp();
 
         if (absrap<=2.4 and absrap>2.) {
           if (nonPrompt) _nonPrRapHigh->fill(xp);
           else if (!nonPrompt) _PrRapHigh->fill(xp);
           _IncRapHigh->fill(xp);
         }
         else if (absrap<=2. and absrap>1.5) {
           if (nonPrompt) _nonPrRapMedHigh->fill(xp);
           else if (!nonPrompt) _PrRapMedHigh->fill(xp);
           _IncRapMedHigh->fill(xp);
         }
         else if (absrap<=1.5 and absrap>0.75) {
           if (nonPrompt) _nonPrRapMedLow->fill(xp);
           else if (!nonPrompt) _PrRapMedLow->fill(xp);
           _IncRapMedLow->fill(xp);
         }
 
         else if (absrap<=0.75) {
           if (nonPrompt) _nonPrRapLow->fill(xp);
           else if (!nonPrompt) _PrRapLow->fill(xp);
           _IncRapLow->fill(xp);
         }
       }
     }
 
 
     /// Finalize
     void finalize() {
       double factor = crossSection()/nanobarn*0.0593;
 
       scale(_PrRapHigh      , factor/sumOfWeights());
       scale(_PrRapMedHigh   , factor/sumOfWeights());
       scale(_PrRapMedLow    , factor/sumOfWeights());
       scale(_PrRapLow       , factor/sumOfWeights());
 
       scale(_nonPrRapHigh   , factor/sumOfWeights());
       scale(_nonPrRapMedHigh, factor/sumOfWeights());
       scale(_nonPrRapMedLow , factor/sumOfWeights());
       scale(_nonPrRapLow    , factor/sumOfWeights());
 
       scale(_IncRapHigh     , 1000.*factor/sumOfWeights());
       scale(_IncRapMedHigh  , 1000.*factor/sumOfWeights());
       scale(_IncRapMedLow   , 1000.*factor/sumOfWeights());
       scale(_IncRapLow      , 1000.*factor/sumOfWeights());
 
     }
 
     //@}
 
 
   private:
 
     Histo1DPtr _nonPrRapHigh;
     Histo1DPtr _nonPrRapMedHigh;
     Histo1DPtr _nonPrRapMedLow;
     Histo1DPtr _nonPrRapLow;
 
     Histo1DPtr _PrRapHigh;
     Histo1DPtr _PrRapMedHigh;
     Histo1DPtr _PrRapMedLow;
     Histo1DPtr _PrRapLow;
 
     Histo1DPtr _IncRapHigh;
     Histo1DPtr _IncRapMedHigh;
     Histo1DPtr _IncRapMedLow;
     Histo1DPtr _IncRapLow;
     //@}
 
   };
 
   // The hook for the plugin system
   DECLARE_RIVET_PLUGIN(ATLAS_2011_S9035664);
 
 }
diff --git a/analyses/pluginATLAS/ATLAS_2012_I1204447.cc b/analyses/pluginATLAS/ATLAS_2012_I1204447.cc
--- a/analyses/pluginATLAS/ATLAS_2012_I1204447.cc
+++ b/analyses/pluginATLAS/ATLAS_2012_I1204447.cc
@@ -1,1056 +1,1058 @@
 // -*- C++ -*-
 #include "Rivet/Analysis.hh"
 #include "Rivet/Projections/FinalState.hh"
 #include "Rivet/Projections/ChargedFinalState.hh"
 #include "Rivet/Projections/VisibleFinalState.hh"
 #include "Rivet/Projections/VetoedFinalState.hh"
 #include "Rivet/Projections/IdentifiedFinalState.hh"
 #include "Rivet/Projections/UnstableParticles.hh"
 #include "Rivet/Projections/FastJets.hh"
 
 namespace Rivet {
 
 
   class ATLAS_2012_I1204447 : public Analysis {
   public:
 
     /// Constructor
     ATLAS_2012_I1204447()
       : Analysis("ATLAS_2012_I1204447") {  }
 
 
     /// Book histograms and initialise projections before the run
     void init() {
 
       // To calculate the acceptance without having the fiducial lepton efficiencies included, this part can be turned off
       _use_fiducial_lepton_efficiency = true;
 
       // Random numbers for simulation of ATLAS detector reconstruction efficiency
       srand(160385);
 
       // Read in all signal regions
       _signal_regions = getSignalRegions();
 
       // Set number of events per signal region to 0
       for (size_t i = 0; i < _signal_regions.size(); i++)
         book(_eventCountsPerSR[_signal_regions[i]], "_eventCountsPerSR_" + _signal_regions[i]);
 
       // Final state including all charged and neutral particles
       const FinalState fs((Cuts::etaIn(-5.0, 5.0) && Cuts::pT >=  1*GeV));
       declare(fs, "FS");
 
       // Final state including all charged particles
       declare(ChargedFinalState(Cuts::abseta < 2.5 && Cuts::pT > 1*GeV), "CFS");
 
       // Final state including all visible particles (to calculate MET, Jets etc.)
       declare(VisibleFinalState(Cuts::abseta < 5.0), "VFS");
 
       // Final state including all AntiKt 04 Jets
       VetoedFinalState vfs;
       vfs.addVetoPairId(PID::MUON);
       declare(FastJets(vfs, FastJets::ANTIKT, 0.4), "AntiKtJets04");
 
       // Final state including all unstable particles (including taus)
       declare(UnstableParticles(Cuts::abseta < 5.0 && Cuts::pT > 5*GeV), "UFS");
 
       // Final state including all electrons
       IdentifiedFinalState elecs(Cuts::abseta < 2.47 && Cuts::pT > 10*GeV);
       elecs.acceptIdPair(PID::ELECTRON);
       declare(elecs, "elecs");
 
       // Final state including all muons
       IdentifiedFinalState muons(Cuts::abseta < 2.5 && Cuts::pT > 10*GeV);
       muons.acceptIdPair(PID::MUON);
       declare(muons, "muons");
 
       // Book histograms
       book(_h_HTlep_all  ,"HTlep_all" , 30, 0, 1500);
       book(_h_HTjets_all ,"HTjets_all", 30, 0, 1500);
       book(_h_MET_all    ,"MET_all"   , 20, 0, 1000);
       book(_h_Meff_all   ,"Meff_all"  , 30, 0, 3000);
 
       book(_h_e_n        ,"e_n"  , 10, -0.5, 9.5);
       book(_h_mu_n       ,"mu_n" , 10, -0.5, 9.5);
       book(_h_tau_n      ,"tau_n", 10, -0.5, 9.5);
 
       book(_h_pt_1_3l    ,"pt_1_3l", 100, 0, 2000);
       book(_h_pt_2_3l    ,"pt_2_3l", 100, 0, 2000);
       book(_h_pt_3_3l    ,"pt_3_3l", 100, 0, 2000);
       book(_h_pt_1_2ltau ,"pt_1_2ltau", 100, 0, 2000);
       book(_h_pt_2_2ltau ,"pt_2_2ltau", 100, 0, 2000);
       book(_h_pt_3_2ltau ,"pt_3_2ltau", 100, 0, 2000);
 
       book(_h_excluded   ,"excluded", 2, -0.5, 1.5);
     }
 
 
     /// Perform the per-event analysis
     void analyze(const Event& event) {
 
       // Muons
       Particles muon_candidates;
       const Particles charged_tracks    = apply<ChargedFinalState>(event, "CFS").particles();
       const Particles visible_particles = apply<VisibleFinalState>(event, "VFS").particles();
       for (const Particle& mu : apply<IdentifiedFinalState>(event, "muons").particlesByPt()) {
         // Calculate pTCone30 variable (pT of all tracks within dR<0.3 - pT of muon itself)
         double pTinCone = -mu.pT();
         for (const Particle& track : charged_tracks) {
           if (deltaR(mu.momentum(), track.momentum()) < 0.3)
             pTinCone += track.pT();
         }
 
         // Calculate eTCone30 variable (pT of all visible particles within dR<0.3)
         double eTinCone = 0.;
         for (const Particle& visible_particle : visible_particles) {
           if (visible_particle.abspid() != PID::MUON && inRange(deltaR(mu.momentum(), visible_particle.momentum()), 0.1, 0.3))
             eTinCone += visible_particle.pT();
         }
 
         // Apply reconstruction efficiency and simulate reco
         int muon_id = 13;
         if ( mu.hasAncestor(15) || mu.hasAncestor(-15)) muon_id = 14;
         const double eff = (_use_fiducial_lepton_efficiency) ? apply_reco_eff(muon_id, mu) : 1.0;
         const bool keep_muon = rand()/static_cast<double>(RAND_MAX) <= eff;
 
         // Keep muon if pTCone30/pT < 0.15 and eTCone30/pT < 0.2 and reconstructed
         if (keep_muon && pTinCone/mu.pT() <= 0.15 && eTinCone/mu.pT() < 0.2)
           muon_candidates.push_back(mu);
       }
 
 
       // Electrons
       Particles electron_candidates;
       for (const Particle& e : apply<IdentifiedFinalState>(event, "elecs").particlesByPt()) {
         // Neglect electrons in crack regions
         if (inRange(e.abseta(), 1.37, 1.52)) continue;
 
         // Calculate pTCone30 variable (pT of all tracks within dR<0.3 - pT of electron itself)
         double pTinCone = -e.pT();
         for (const Particle& track : charged_tracks) {
           if (deltaR(e.momentum(), track.momentum()) < 0.3) pTinCone += track.pT();
         }
 
         // Calculate eTCone30 variable (pT of all visible particles (except muons) within dR<0.3)
         double eTinCone = 0.;
         for (const Particle& visible_particle : visible_particles) {
           if (visible_particle.abspid() != PID::MUON && inRange(deltaR(e.momentum(), visible_particle.momentum()), 0.1, 0.3))
             eTinCone += visible_particle.pT();
         }
 
         // Apply reconstruction efficiency and simulate reco
         int elec_id = 11;
         if (e.hasAncestor(15) || e.hasAncestor(-15)) elec_id = 12;
         const double eff = (_use_fiducial_lepton_efficiency) ? apply_reco_eff(elec_id, e) : 1.0;
         const bool keep_elec = rand()/static_cast<double>(RAND_MAX) <= eff;
 
         // Keep electron if pTCone30/pT < 0.13 and eTCone30/pT < 0.2 and reconstructed
         if (keep_elec && pTinCone/e.pT() <= 0.13 && eTinCone/e.pT() < 0.2)
           electron_candidates.push_back(e);
       }
 
 
       // Taus
       /// @todo This could benefit from a tau finder projection
       Particles tau_candidates;
       for (const Particle& tau : apply<UnstableParticles>(event, "UFS").particlesByPt()) {
         // Only pick taus out of all unstable particles
         if (tau.abspid() != PID::TAU) continue;
 
         // Check that tau has decayed into daughter particles
         /// @todo Huh? Unstable taus with no decay vtx? Can use Particle.isStable()? But why in this situation?
         if (tau.genParticle()->end_vertex() == 0) continue;
 
         // Calculate visible tau pT from pT of tau neutrino in tau decay for pT and |eta| cuts
         FourMomentum daughter_tau_neutrino_momentum = get_tau_neutrino_mom(tau);
         Particle tau_vis = tau;
         tau_vis.setMomentum(tau.momentum()-daughter_tau_neutrino_momentum);
         // keep only taus in certain eta region and above 15 GeV of visible tau pT
         if ( tau_vis.pT() <= 15.0*GeV || tau_vis.abseta() > 2.5) continue;
 
         // Get prong number (number of tracks) in tau decay and check if tau decays leptonically
         unsigned int nprong = 0;
         bool lep_decaying_tau = false;
         get_prong_number(tau.genParticle(), nprong, lep_decaying_tau);
 
         // Apply reconstruction efficiency
         int tau_id = 15;
         if (nprong == 1) tau_id = 15;
         else if (nprong == 3) tau_id = 16;
 
         // Get fiducial lepton efficiency simulate reco efficiency
         const double eff = (_use_fiducial_lepton_efficiency) ? apply_reco_eff(tau_id, tau_vis) : 1.0;
         const bool keep_tau = rand()/static_cast<double>(RAND_MAX) <= eff;
 
         // Keep tau if nprong = 1, it decays hadronically, and it's reconstructed by the detector
         if ( !lep_decaying_tau && nprong == 1 && keep_tau) tau_candidates.push_back(tau_vis);
       }
 
 
       // Jets (all anti-kt R=0.4 jets with pT > 25 GeV and eta < 4.9)
       Jets jet_candidates;
       for (const Jet& jet : apply<FastJets>(event, "AntiKtJets04").jetsByPt(25*GeV)) {
         if (jet.abseta() < 4.9) jet_candidates.push_back(jet);
       }
 
 
       // ETmiss
       Particles vfs_particles = apply<VisibleFinalState>(event, "VFS").particles();
       FourMomentum pTmiss;
       for (const Particle& p : vfs_particles) pTmiss -= p.momentum();
       double eTmiss = pTmiss.pT()/GeV;
 
 
       //------------------
       // Overlap removal
 
       // electron - electron
       Particles electron_candidates_2;
       for (size_t ie = 0; ie < electron_candidates.size(); ++ie) {
         const Particle & e = electron_candidates[ie];
         bool away = true;
         // If electron pair within dR < 0.1: remove electron with lower pT
         for (size_t ie2=0; ie2 < electron_candidates_2.size(); ++ie2) {
           if ( deltaR( e.momentum(), electron_candidates_2[ie2].momentum()) < 0.1 ) {
             away = false;
             break;
           }
         }
         // If isolated keep it
         if ( away )
           electron_candidates_2.push_back( e );
       }
       // jet - electron
       Jets recon_jets;
       for (const Jet& jet : jet_candidates) {
         bool away = true;
         // if jet within dR < 0.2 of electron: remove jet
         for (const Particle& e : electron_candidates_2) {
           if (deltaR(e.momentum(), jet.momentum()) < 0.2) {
             away = false;
             break;
           }
         }
         // jet - tau
         if (away)  {
           // If jet within dR < 0.2 of tau: remove jet
           for (const Particle& tau : tau_candidates) {
             if (deltaR(tau.momentum(), jet.momentum()) < 0.2) {
               away = false;
               break;
             }
           }
         }
         // If isolated keep it
         if ( away )
           recon_jets.push_back( jet );
       }
 
 
       // electron - jet
       Particles recon_leptons, recon_e;
       for (size_t ie = 0; ie < electron_candidates_2.size(); ++ie) {
         const Particle& e = electron_candidates_2[ie];
         // If electron within 0.2 < dR < 0.4 from any jets: remove electron
         bool away = true;
         for (const Jet& jet : recon_jets) {
           if (deltaR(e.momentum(), jet.momentum()) < 0.4) {
             away = false;
             break;
           }
         }
         // electron - muon
         // if electron within dR < 0.1 of a muon: remove electron
         if (away) {
           for (const Particle& mu : muon_candidates) {
             if (deltaR(mu.momentum(), e.momentum()) < 0.1) {
               away = false;
               break;
             }
           }
         }
         // If isolated keep it
         if (away)  {
           recon_e += e;
           recon_leptons += e;
         }
       }
 
 
       // tau - electron
       Particles recon_tau;
       for ( const Particle& tau : tau_candidates ) {
         bool away = true;
         // If tau within dR < 0.2 of an electron: remove tau
         for ( const Particle& e : recon_e ) {
           if (deltaR( tau.momentum(), e.momentum()) < 0.2) {
             away = false;
             break;
           }
         }
         // tau - muon
         // If tau within dR < 0.2 of a muon: remove tau
         if (away)  {
           for (const Particle& mu : muon_candidates) {
             if (deltaR(tau.momentum(), mu.momentum()) < 0.2) {
               away = false;
               break;
             }
           }
         }
         // If isolated keep it
         if (away) recon_tau.push_back( tau );
       }
 
       // Muon - jet isolation
       Particles recon_mu, trigger_mu;
       // If muon within dR < 0.4 of a jet, remove muon
       for (const Particle& mu : muon_candidates) {
         bool away = true;
         for (const Jet& jet : recon_jets) {
           if ( deltaR( mu.momentum(), jet.momentum()) < 0.4 ) {
             away = false;
             break;
           }
         }
         if (away) {
           recon_mu.push_back( mu );
           recon_leptons.push_back( mu );
           if (mu.abseta() < 2.4) trigger_mu.push_back( mu );
         }
       }
 
       // End overlap removal
       //------------------
 
 
       // Jet cleaning
       if (rand()/static_cast<double>(RAND_MAX) <= 0.42) {
         for (const Jet& jet : recon_jets) {
           const double eta = jet.rapidity();
           const double phi = jet.azimuthalAngle(MINUSPI_PLUSPI);
           if (jet.pT() > 25*GeV && inRange(eta, -0.1, 1.5) && inRange(phi, -0.9, -0.5)) vetoEvent;
         }
       }
 
 
       // Post-isolation event cuts
       // Require at least 3 charged tracks in event
       if (charged_tracks.size() < 3) vetoEvent;
 
       // And at least one e/mu passing trigger
       if (!( !recon_e   .empty() && recon_e[0]   .pT() > 25*GeV)  &&
           !( !trigger_mu.empty() && trigger_mu[0].pT() > 25*GeV) ) {
         MSG_DEBUG("Hardest lepton fails trigger");
         vetoEvent;
       }
 
       // And only accept events with at least 2 electrons and muons and at least 3 leptons in total
       if (recon_mu.size() + recon_e.size() + recon_tau.size() < 3 || recon_leptons.size() < 2) vetoEvent;
 
       // Sort leptons by decreasing pT
       sortByPt(recon_leptons);
       sortByPt(recon_tau);
 
       // Calculate HTlep, fill lepton pT histograms & store chosen combination of 3 leptons
       double HTlep = 0.;
       Particles chosen_leptons;
       if ( recon_leptons.size() > 2 ) {
         _h_pt_1_3l->fill(recon_leptons[0].perp()/GeV);
         _h_pt_2_3l->fill(recon_leptons[1].perp()/GeV);
         _h_pt_3_3l->fill(recon_leptons[2].perp()/GeV);
         HTlep = (recon_leptons[0].pT() + recon_leptons[1].pT() + recon_leptons[2].pT())/GeV;
         chosen_leptons.push_back( recon_leptons[0] );
         chosen_leptons.push_back( recon_leptons[1] );
         chosen_leptons.push_back( recon_leptons[2] );
       }
       else {
         _h_pt_1_2ltau->fill(recon_leptons[0].perp()/GeV);
         _h_pt_2_2ltau->fill(recon_leptons[1].perp()/GeV);
         _h_pt_3_2ltau->fill(recon_tau[0].perp()/GeV);
         HTlep = (recon_leptons[0].pT() + recon_leptons[1].pT() + recon_tau[0].pT())/GeV ;
         chosen_leptons.push_back( recon_leptons[0] );
         chosen_leptons.push_back( recon_leptons[1] );
         chosen_leptons.push_back( recon_tau[0] );
       }
 
       // Number of prompt e/mu and had taus
       _h_e_n  ->fill(recon_e.size());
       _h_mu_n ->fill(recon_mu.size());
       _h_tau_n->fill(recon_tau.size());
 
       // Calculate HTjets
       double HTjets = 0.;
       for ( const Jet & jet : recon_jets )
         HTjets += jet.perp()/GeV;
 
       // Calculate meff
       double meff = eTmiss + HTjets;
       Particles all_leptons;
       for ( const Particle & e  : recon_e  )  {
         meff += e.perp()/GeV;
         all_leptons.push_back( e );
       }
       for ( const Particle & mu : recon_mu )  {
         meff += mu.perp()/GeV;
         all_leptons.push_back( mu );
       }
       for ( const Particle & tau : recon_tau )  {
         meff += tau.perp()/GeV;
         all_leptons.push_back( tau );
       }
 
       // Fill histogram of kinematic variables
       _h_HTlep_all ->fill(HTlep);
       _h_HTjets_all->fill(HTjets);
       _h_MET_all   ->fill(eTmiss);
       _h_Meff_all  ->fill(meff);
 
       // Determine signal region (3l/2ltau, onZ/offZ)
       string basic_signal_region;
       if ( recon_mu.size() + recon_e.size() > 2 )
         basic_signal_region += "3l_";
       else if ( (recon_mu.size() + recon_e.size() == 2) && (recon_tau.size() > 0))
         basic_signal_region += "2ltau_";
       // Is there an OSSF pair or a three lepton combination with an invariant mass close to the Z mass
       int onZ = isonZ(chosen_leptons);
       if      (onZ == 1)   basic_signal_region += "onZ";
       else if (onZ == 0)   basic_signal_region += "offZ";
       // Check in which signal regions this event falls and adjust event counters
       fillEventCountsPerSR(basic_signal_region, onZ, HTlep, eTmiss, HTjets, meff);
     }
 
 
     /// Normalise histograms etc., after the run
     void finalize() {
 
       // Normalize to an integrated luminosity of 1 fb-1
       double norm = crossSection()/femtobarn/sumOfWeights();
       string best_signal_region = "";
       double ratio_best_SR = 0.;
 
       // Loop over all signal regions and find signal region with best sensitivity (ratio signal events/visible cross-section)
       for (size_t i = 0; i < _signal_regions.size(); i++)  {
         double signal_events = _eventCountsPerSR[_signal_regions[i]]->val() * norm;
         // Use expected upper limits to find best signal region
         double UL95  = getUpperLimit(_signal_regions[i], false);
         double ratio = signal_events / UL95;
         if (ratio > ratio_best_SR)  {
           best_signal_region = _signal_regions[i];
           ratio_best_SR = ratio;
         }
       }
 
       double signal_events_best_SR = _eventCountsPerSR[best_signal_region]->val() * norm;
       double exp_UL_best_SR = getUpperLimit(best_signal_region, false);
       double obs_UL_best_SR = getUpperLimit(best_signal_region, true);
 
       // Print out result
       cout << "----------------------------------------------------------------------------------------" << endl;
       cout << "Best signal region: " << best_signal_region << endl;
       cout << "Normalized number of signal events in this best signal region (per fb-1): " << signal_events_best_SR << endl;
       cout << "Efficiency*Acceptance: " <<  _eventCountsPerSR[best_signal_region]->val()/sumOfWeights() << endl;
       cout << "Cross-section [fb]: " << crossSection()/femtobarn << endl;
       cout << "Expected visible cross-section (per fb-1): " << exp_UL_best_SR << endl;
       cout << "Ratio (signal events / expected visible cross-section): " << ratio_best_SR << endl;
       cout << "Observed visible cross-section (per fb-1): " << obs_UL_best_SR << endl;
       cout << "Ratio (signal events / observed visible cross-section): " <<  signal_events_best_SR/obs_UL_best_SR << endl;
       cout << "----------------------------------------------------------------------------------------" << endl;
 
       cout << "Using the EXPECTED limits (visible cross-section) of the analysis: " << endl;
       if (signal_events_best_SR > exp_UL_best_SR)  {
         cout << "Since the number of signal events > the visible cross-section, this model/grid point is EXCLUDED with 95% CL." << endl;
         _h_excluded->fill(1);
       }
       else  {
         cout << "Since the number of signal events < the visible cross-section, this model/grid point is NOT EXCLUDED." << endl;
         _h_excluded->fill(0);
       }
       cout << "----------------------------------------------------------------------------------------" << endl;
 
       cout << "Using the OBSERVED limits (visible cross-section) of the analysis: " << endl;
       if (signal_events_best_SR > obs_UL_best_SR)  {
         cout << "Since the number of signal events > the visible cross-section, this model/grid point is EXCLUDED with 95% CL." << endl;
         _h_excluded->fill(1);
       }
       else  {
         cout << "Since the number of signal events < the visible cross-section, this model/grid point is NOT EXCLUDED." << endl;
         _h_excluded->fill(0);
       }
       cout << "----------------------------------------------------------------------------------------" << endl;
 
 
       // Normalize to cross section
       if (norm != 0)  {
         scale(_h_HTlep_all,  norm);
         scale(_h_HTjets_all, norm);
         scale(_h_MET_all,    norm);
         scale(_h_Meff_all,   norm);
 
         scale(_h_pt_1_3l,    norm);
         scale(_h_pt_2_3l,    norm);
         scale(_h_pt_3_3l,    norm);
         scale(_h_pt_1_2ltau, norm);
         scale(_h_pt_2_2ltau, norm);
         scale(_h_pt_3_2ltau, norm);
 
         scale(_h_e_n,        norm);
         scale(_h_mu_n,       norm);
         scale(_h_tau_n,      norm);
 
         scale(_h_excluded,   signal_events_best_SR);
       }
     }
 
 
     /// Helper functions
     //@{
 
     /// Function giving a list of all signal regions
     vector<string> getSignalRegions()  {
 
       // List of basic signal regions
       vector<string> basic_signal_regions;
       basic_signal_regions.push_back("3l_offZ");
       basic_signal_regions.push_back("3l_onZ");
       basic_signal_regions.push_back("2ltau_offZ");
       basic_signal_regions.push_back("2ltau_onZ");
 
       // List of kinematic variables
       vector<string> kinematic_variables;
       kinematic_variables.push_back("HTlep");
       kinematic_variables.push_back("METStrong");
       kinematic_variables.push_back("METWeak");
       kinematic_variables.push_back("Meff");
       kinematic_variables.push_back("MeffStrong");
 
       vector<string> signal_regions;
       // Loop over all kinematic variables and basic signal regions
       for (size_t i0 = 0; i0 < kinematic_variables.size(); i0++)  {
         for (size_t i1 = 0; i1 < basic_signal_regions.size(); i1++)  {
           // Is signal region onZ?
           int onZ = (basic_signal_regions[i1].find("onZ") != string::npos) ? 1 : 0;
           // Get cut values for this kinematic variable
           vector<int> cut_values = getCutsPerSignalRegion(kinematic_variables[i0], onZ);
           // Loop over all cut values
           for (size_t i2 = 0; i2 < cut_values.size(); i2++)  {
             // push signal region into vector
             signal_regions.push_back( (kinematic_variables[i0] + "_" + basic_signal_regions[i1] + "_cut_" + toString(i2)) );
           }
         }
       }
       return signal_regions;
     }
 
 
     /// Function giving all cut vales per kinematic variable (taking onZ for MET into account)
     vector<int> getCutsPerSignalRegion(const string& signal_region, int onZ=0)  {
       vector<int> cutValues;
 
       // Cut values for HTlep
       if (signal_region.compare("HTlep") == 0)  {
         cutValues.push_back(0);
         cutValues.push_back(100);
         cutValues.push_back(150);
         cutValues.push_back(200);
         cutValues.push_back(300);
       }
       // Cut values for METStrong (HTjets > 100 GeV) and METWeak (HTjets < 100 GeV)
       else if (signal_region.compare("METStrong") == 0 || signal_region.compare("METWeak") == 0)  {
         if      (onZ == 0) cutValues.push_back(0);
         else if (onZ == 1) cutValues.push_back(20);
         cutValues.push_back(50);
         cutValues.push_back(75);
       }
       // Cut values for Meff and MeffStrong (MET > 75 GeV)
       if (signal_region.compare("Meff") == 0 || signal_region.compare("MeffStrong") == 0)  {
         cutValues.push_back(0);
         cutValues.push_back(150);
         cutValues.push_back(300);
         cutValues.push_back(500);
       }
 
       return cutValues;
     }
 
 
     /// function fills map EventCountsPerSR by looping over all signal regions
     /// and looking if the event falls into this signal region
     void fillEventCountsPerSR(const string& basic_signal_region, int onZ,
                               double HTlep, double eTmiss,
                               double HTjets, double meff)  {
 
       // Get cut values for HTlep, loop over them and add event if cut is passed
       vector<int> cut_values = getCutsPerSignalRegion("HTlep", onZ);
       for (size_t i = 0; i < cut_values.size(); i++)  {
         if (HTlep > cut_values[i])
           _eventCountsPerSR[("HTlep_" + basic_signal_region + "_cut_" + toString(cut_values[i]))]->fill();
       }
 
       // Get cut values for METStrong, loop over them and add event if cut is passed
       cut_values = getCutsPerSignalRegion("METStrong", onZ);
       for (size_t i = 0; i < cut_values.size(); i++)  {
         if (eTmiss > cut_values[i] && HTjets > 100.)
           _eventCountsPerSR[("METStrong_" + basic_signal_region + "_cut_" + toString(cut_values[i]))]->fill();
       }
 
       // Get cut values for METWeak, loop over them and add event if cut is passed
       cut_values = getCutsPerSignalRegion("METWeak", onZ);
       for (size_t i = 0; i < cut_values.size(); i++)  {
         if (eTmiss > cut_values[i] && HTjets <= 100.)
           _eventCountsPerSR[("METWeak_" + basic_signal_region + "_cut_" + toString(cut_values[i]))]->fill();
       }
 
       // Get cut values for Meff, loop over them and add event if cut is passed
       cut_values = getCutsPerSignalRegion("Meff", onZ);
       for (size_t i = 0; i < cut_values.size(); i++)  {
         if (meff > cut_values[i])
           _eventCountsPerSR[("Meff_" + basic_signal_region + "_cut_" + toString(cut_values[i]))]->fill();
       }
 
       // Get cut values for MeffStrong, loop over them and add event if cut is passed
       cut_values = getCutsPerSignalRegion("MeffStrong", onZ);
       for (size_t i = 0; i < cut_values.size(); i++)  {
         if (meff > cut_values[i] && eTmiss > 75.)
           _eventCountsPerSR[("MeffStrong_" + basic_signal_region + "_cut_" + toString(cut_values[i]))]->fill();
       }
     }
 
 
     /// Function returning 4-vector of daughter-particle if it is a tau neutrino
     /// @todo Move to TauFinder and make less HepMC-ish
     FourMomentum get_tau_neutrino_mom(const Particle& p)  {
       assert(p.abspid() == PID::TAU);
       ConstGenVertexPtr dv = p.genParticle()->end_vertex();
       assert(dv != nullptr);
       for(ConstGenParticlePtr pp: HepMCUtils::particles(dv, Relatives::CHILDREN)){
         if (abs(pp->pdg_id()) == PID::NU_TAU) return FourMomentum(pp->momentum());
       }
       return FourMomentum();
     }
 
 
     /// Function calculating the prong number of taus
     /// @todo Move to TauFinder and make less HepMC-ish
     void get_prong_number(ConstGenParticlePtr p, unsigned int& nprong, bool& lep_decaying_tau) {
       assert(p != nullptr);
       //const int tau_barcode = p->barcode();
       ConstGenVertexPtr dv = p->end_vertex();
       assert(dv != nullptr);
       for(ConstGenParticlePtr pp: HepMCUtils::particles(dv, Relatives::CHILDREN)){
         // If they have status 1 and are charged they will produce a track and the prong number is +1
         if (pp->status() == 1 )  {
           const int id = pp->pdg_id();
           if (Rivet::PID::charge(id) != 0 ) ++nprong;
           // Check if tau decays leptonically
           // @todo Can a tau decay include a tau in its decay daughters?!
           if ((abs(id) == PID::ELECTRON || abs(id) == PID::MUON || abs(id) == PID::TAU) && abs(p->pdg_id()) == PID::TAU) lep_decaying_tau = true;
         }
         // If the status of the daughter particle is 2 it is unstable and the further decays are checked
         else if (pp->status() == 2 )  {
           get_prong_number(pp, nprong, lep_decaying_tau);
         }
       }
     }
 
 
     /// Function giving fiducial lepton efficiency
     double apply_reco_eff(int flavor, const Particle& p) {
       float pt = p.pT()/GeV;
       float eta = p.eta();
 
       double eff = 0.;
       //double err = 0.;
 
       if (flavor == 11) { // weight prompt electron -- now including data/MC ID SF in eff.
         //float rho = 0.820;
         float p0 = 7.34;  float p1 = 0.8977;
         //float ep0= 0.5 ;  float ep1= 0.0087;
         eff = p1 - p0/pt;
 
         //double err0 = ep0/pt; // d(eff)/dp0
         //double err1 = ep1;    // d(eff)/dp1
         //err = sqrt(err0*err0 + err1*err1 - 2*rho*err0*err1);
 
         double avgrate = 0.6867;
         float wz_ele_eta[] = {0.588717,0.603674,0.666135,0.747493,0.762202,0.675051,0.751606,0.745569,0.665333,0.610432,0.592693,};
         //float ewz_ele_eta[] ={0.00292902,0.002476,0.00241209,0.00182319,0.00194339,0.00299785,0.00197339,0.00182004,0.00241793,0.00245997,0.00290394,};
         int ibin = 3;
 
         if (eta >= -2.5 && eta < -2.0) ibin = 0;
         if (eta >= -2.0 && eta < -1.5) ibin = 1;
         if (eta >= -1.5 && eta < -1.0) ibin = 2;
         if (eta >= -1.0 && eta < -0.5) ibin = 3;
         if (eta >= -0.5 && eta < -0.1) ibin = 4;
         if (eta >= -0.1 && eta <  0.1) ibin = 5;
         if (eta >=  0.1 && eta <  0.5) ibin = 6;
         if (eta >=  0.5 && eta <  1.0) ibin = 7;
         if (eta >=  1.0 && eta <  1.5) ibin = 8;
         if (eta >=  1.5 && eta <  2.0) ibin = 9;
         if (eta >=  2.0 && eta <  2.5) ibin = 10;
 
         double eff_eta = wz_ele_eta[ibin];
         //double err_eta = ewz_ele_eta[ibin];
 
         eff = (eff*eff_eta)/avgrate;
       }
 
       if (flavor == 12)  { // weight electron from tau
         //float rho = 0.884;
         float p0 = 6.799;  float p1 = 0.842;
         //float ep0= 0.664;  float ep1= 0.016;
         eff = p1 - p0/pt;
 
         //double err0 = ep0/pt; // d(eff)/dp0
         //double err1 = ep1;    // d(eff)/dp1
         //err = sqrt(err0*err0 + err1*err1 - 2*rho*err0*err1);
 
         double avgrate = 0.5319;
         float wz_elet_eta[] = {0.468945,0.465953,0.489545,0.58709,0.59669,0.515829,0.59284,0.575828,0.498181,0.463536,0.481738,};
         //float ewz_elet_eta[] ={0.00933795,0.00780868,0.00792679,0.00642083,0.00692652,0.0101568,0.00698452,0.00643524,0.0080002,0.00776238,0.0094699,};
         int ibin = 3;
 
         if (eta >= -2.5 && eta < -2.0) ibin = 0;
         if (eta >= -2.0 && eta < -1.5) ibin = 1;
         if (eta >= -1.5 && eta < -1.0) ibin = 2;
         if (eta >= -1.0 && eta < -0.5) ibin = 3;
         if (eta >= -0.5 && eta < -0.1) ibin = 4;
         if (eta >= -0.1 && eta <  0.1) ibin = 5;
         if (eta >=  0.1 && eta <  0.5) ibin = 6;
         if (eta >=  0.5 && eta <  1.0) ibin = 7;
         if (eta >=  1.0 && eta <  1.5) ibin = 8;
         if (eta >=  1.5 && eta <  2.0) ibin = 9;
         if (eta >=  2.0 && eta <  2.5) ibin = 10;
 
         double eff_eta = wz_elet_eta[ibin];
         //double err_eta = ewz_elet_eta[ibin];
 
         eff = (eff*eff_eta)/avgrate;
 
       }
 
       if (flavor == 13)  {// weight prompt muon
 
         //if eta>0.1
         float p0 = -18.21;  float p1 = 14.83;  float p2 = 0.9312;
         //float ep0= 5.06;    float ep1= 1.9;    float ep2=0.00069;
 
         if ( fabs(eta) < 0.1)  {
           p0  = 7.459; p1 = 2.615; p2  = 0.5138;
           //ep0 = 10.4; ep1 = 4.934; ep2 = 0.0034;
         }
 
         double arg = ( pt-p0 )/( 2.*p1 ) ;
         eff = 0.5 * p2 * (1.+erf(arg));
         //err = 0.1*eff;
       }
 
       if (flavor == 14)  {// weight muon from tau
 
         if (fabs(eta) < 0.1) {
           float p0 = -1.756;  float p1 = 12.38;  float p2 = 0.4441;
           //float ep0= 10.39;   float ep1= 7.9;  float ep2=0.022;
           double arg = ( pt-p0 )/( 2.*p1 ) ;
           eff = 0.5 * p2 * (1.+erf(arg));
           //err = 0.1*eff;
         }
         else {
           float p0 = 2.102;  float p1 = 0.8293;
           //float ep0= 0.271;  float ep1= 0.0083;
           eff = p1 - p0/pt;
           //double err0 = ep0/pt; // d(eff)/dp0
           //double err1 = ep1;    // d(eff)/dp1
           //err = sqrt(err0*err0 + err1*err1 - 2*rho*err0*err1);
         }
       }
 
       if (flavor == 15)  {// weight hadronic tau 1p
 
         float wz_tau1p[] = {0.0249278,0.146978,0.225049,0.229212,0.21519,0.206152,0.201559,0.197917,0.209249,0.228336,0.193548,};
         //float ewz_tau1p[] ={0.00178577,0.00425252,0.00535052,0.00592126,0.00484684,0.00612941,0.00792099,0.0083006,0.0138307,0.015568,0.0501751,};
         int ibin = 0;
         if (pt > 15)  ibin = 1;
         if (pt > 20)  ibin = 2;
         if (pt > 25)  ibin = 3;
         if (pt > 30)  ibin = 4;
         if (pt > 40)  ibin = 5;
         if (pt > 50)  ibin = 6;
         if (pt > 60)  ibin = 7;
         if (pt > 80)  ibin = 8;
         if (pt > 100) ibin = 9;
         if (pt > 200) ibin = 10;
 
         eff = wz_tau1p[ibin];
         //err = ewz_tau1p[ibin];
 
 
         double avgrate = 0.1718;
         float wz_tau1p_eta[] = {0.162132,0.176393,0.139619,0.178813,0.185144,0.210027,0.203937,0.178688,0.137034,0.164216,0.163713,};
         //float ewz_tau1p_eta[] ={0.00706705,0.00617989,0.00506798,0.00525172,0.00581865,0.00865675,0.00599245,0.00529877,0.00506368,0.00617025,0.00726219,};
 
         ibin = 3;
         if (eta >= -2.5 && eta < -2.0) ibin = 0;
         if (eta >= -2.0 && eta < -1.5) ibin = 1;
         if (eta >= -1.5 && eta < -1.0) ibin = 2;
         if (eta >= -1.0 && eta < -0.5) ibin = 3;
         if (eta >= -0.5 && eta < -0.1) ibin = 4;
         if (eta >= -0.1 && eta <  0.1) ibin = 5;
         if (eta >=  0.1 && eta <  0.5) ibin = 6;
         if (eta >=  0.5 && eta <  1.0) ibin = 7;
         if (eta >=  1.0 && eta <  1.5) ibin = 8;
         if (eta >=  1.5 && eta <  2.0) ibin = 9;
         if (eta >=  2.0 && eta <  2.5) ibin = 10;
 
         double eff_eta = wz_tau1p_eta[ibin];
         //double err_eta = ewz_tau1p_eta[ibin];
 
         eff = (eff*eff_eta)/avgrate;
       }
 
       if (flavor == 16)  { //weight hadronic tau 3p
 
         float wz_tau3p[] = {0.000587199,0.00247181,0.0013031,0.00280112,};
         //float ewz_tau3p[] ={0.000415091,0.000617187,0.000582385,0.00197792,};
 
         int ibin = 0;
         if (pt > 15) ibin = 1;
         if (pt > 20) ibin = 2;
         if (pt > 40) ibin = 3;
         if (pt > 80) ibin = 4;
 
         eff = wz_tau3p[ibin];
         //err = ewz_tau3p[ibin];
       }
 
       return eff;
     }
 
 
     /// Function giving observed upper limit (visible cross-section)
     double getUpperLimit(const string& signal_region, bool observed)  {
       map<string,double> upperLimitsObserved;
       upperLimitsObserved["HTlep_3l_offZ_cut_0"] = 11.;
       upperLimitsObserved["HTlep_3l_offZ_cut_100"] = 8.7;
       upperLimitsObserved["HTlep_3l_offZ_cut_150"] = 4.0;
       upperLimitsObserved["HTlep_3l_offZ_cut_200"] = 4.4;
       upperLimitsObserved["HTlep_3l_offZ_cut_300"] = 1.6;
       upperLimitsObserved["HTlep_2ltau_offZ_cut_0"] = 25.;
       upperLimitsObserved["HTlep_2ltau_offZ_cut_100"] = 14.;
       upperLimitsObserved["HTlep_2ltau_offZ_cut_150"] = 6.1;
       upperLimitsObserved["HTlep_2ltau_offZ_cut_200"] = 3.3;
       upperLimitsObserved["HTlep_2ltau_offZ_cut_300"] = 1.2;
       upperLimitsObserved["HTlep_3l_onZ_cut_0"] = 48.;
       upperLimitsObserved["HTlep_3l_onZ_cut_100"] = 38.;
       upperLimitsObserved["HTlep_3l_onZ_cut_150"] = 14.;
       upperLimitsObserved["HTlep_3l_onZ_cut_200"] = 7.2;
       upperLimitsObserved["HTlep_3l_onZ_cut_300"] = 4.5;
       upperLimitsObserved["HTlep_2ltau_onZ_cut_0"] = 85.;
       upperLimitsObserved["HTlep_2ltau_onZ_cut_100"] = 53.;
       upperLimitsObserved["HTlep_2ltau_onZ_cut_150"] = 11.0;
       upperLimitsObserved["HTlep_2ltau_onZ_cut_200"] = 5.2;
       upperLimitsObserved["HTlep_2ltau_onZ_cut_300"] = 3.0;
       upperLimitsObserved["METStrong_3l_offZ_cut_0"] = 2.6;
       upperLimitsObserved["METStrong_3l_offZ_cut_50"] = 2.1;
       upperLimitsObserved["METStrong_3l_offZ_cut_75"] = 2.1;
       upperLimitsObserved["METStrong_2ltau_offZ_cut_0"] = 4.2;
       upperLimitsObserved["METStrong_2ltau_offZ_cut_50"] = 3.1;
       upperLimitsObserved["METStrong_2ltau_offZ_cut_75"] = 2.6;
       upperLimitsObserved["METStrong_3l_onZ_cut_20"] = 11.0;
       upperLimitsObserved["METStrong_3l_onZ_cut_50"] = 6.4;
       upperLimitsObserved["METStrong_3l_onZ_cut_75"] = 5.1;
       upperLimitsObserved["METStrong_2ltau_onZ_cut_20"] = 5.9;
       upperLimitsObserved["METStrong_2ltau_onZ_cut_50"] = 3.4;
       upperLimitsObserved["METStrong_2ltau_onZ_cut_75"] = 1.2;
       upperLimitsObserved["METWeak_3l_offZ_cut_0"] = 11.;
       upperLimitsObserved["METWeak_3l_offZ_cut_50"] = 5.3;
       upperLimitsObserved["METWeak_3l_offZ_cut_75"] = 3.1;
       upperLimitsObserved["METWeak_2ltau_offZ_cut_0"] = 23.;
       upperLimitsObserved["METWeak_2ltau_offZ_cut_50"] = 4.3;
       upperLimitsObserved["METWeak_2ltau_offZ_cut_75"] = 3.1;
       upperLimitsObserved["METWeak_3l_onZ_cut_20"] = 41.;
       upperLimitsObserved["METWeak_3l_onZ_cut_50"] = 16.;
       upperLimitsObserved["METWeak_3l_onZ_cut_75"] = 8.0;
       upperLimitsObserved["METWeak_2ltau_onZ_cut_20"] = 80.;
       upperLimitsObserved["METWeak_2ltau_onZ_cut_50"] = 4.4;
       upperLimitsObserved["METWeak_2ltau_onZ_cut_75"] = 1.8;
       upperLimitsObserved["Meff_3l_offZ_cut_0"] = 11.;
       upperLimitsObserved["Meff_3l_offZ_cut_150"] = 8.1;
       upperLimitsObserved["Meff_3l_offZ_cut_300"] = 3.1;
       upperLimitsObserved["Meff_3l_offZ_cut_500"] = 2.1;
       upperLimitsObserved["Meff_2ltau_offZ_cut_0"] = 25.;
       upperLimitsObserved["Meff_2ltau_offZ_cut_150"] = 12.;
       upperLimitsObserved["Meff_2ltau_offZ_cut_300"] = 3.9;
       upperLimitsObserved["Meff_2ltau_offZ_cut_500"] = 2.2;
       upperLimitsObserved["Meff_3l_onZ_cut_0"] = 48.;
       upperLimitsObserved["Meff_3l_onZ_cut_150"] = 37.;
       upperLimitsObserved["Meff_3l_onZ_cut_300"] = 11.;
       upperLimitsObserved["Meff_3l_onZ_cut_500"] = 4.8;
       upperLimitsObserved["Meff_2ltau_onZ_cut_0"] = 85.;
       upperLimitsObserved["Meff_2ltau_onZ_cut_150"] = 28.;
       upperLimitsObserved["Meff_2ltau_onZ_cut_300"] = 5.9;
       upperLimitsObserved["Meff_2ltau_onZ_cut_500"] = 1.9;
       upperLimitsObserved["MeffStrong_3l_offZ_cut_0"] = 3.8;
       upperLimitsObserved["MeffStrong_3l_offZ_cut_150"] = 3.8;
       upperLimitsObserved["MeffStrong_3l_offZ_cut_300"] = 2.8;
       upperLimitsObserved["MeffStrong_3l_offZ_cut_500"] = 2.1;
       upperLimitsObserved["MeffStrong_2ltau_offZ_cut_0"] = 3.9;
       upperLimitsObserved["MeffStrong_2ltau_offZ_cut_150"] = 4.0;
       upperLimitsObserved["MeffStrong_2ltau_offZ_cut_300"] = 2.9;
       upperLimitsObserved["MeffStrong_2ltau_offZ_cut_500"] = 1.5;
       upperLimitsObserved["MeffStrong_3l_onZ_cut_0"] = 10.0;
       upperLimitsObserved["MeffStrong_3l_onZ_cut_150"] = 10.0;
       upperLimitsObserved["MeffStrong_3l_onZ_cut_300"] = 6.8;
       upperLimitsObserved["MeffStrong_3l_onZ_cut_500"] = 3.9;
       upperLimitsObserved["MeffStrong_2ltau_onZ_cut_0"] = 1.6;
       upperLimitsObserved["MeffStrong_2ltau_onZ_cut_150"] = 1.4;
       upperLimitsObserved["MeffStrong_2ltau_onZ_cut_300"] = 1.5;
       upperLimitsObserved["MeffStrong_2ltau_onZ_cut_500"] = 0.9;
 
       // Expected upper limits are also given but not used in this analysis
       map<string,double> upperLimitsExpected;
       upperLimitsExpected["HTlep_3l_offZ_cut_0"] = 11.;
       upperLimitsExpected["HTlep_3l_offZ_cut_100"] = 8.5;
       upperLimitsExpected["HTlep_3l_offZ_cut_150"] = 4.6;
       upperLimitsExpected["HTlep_3l_offZ_cut_200"] = 3.6;
       upperLimitsExpected["HTlep_3l_offZ_cut_300"] = 1.9;
       upperLimitsExpected["HTlep_2ltau_offZ_cut_0"] = 23.;
       upperLimitsExpected["HTlep_2ltau_offZ_cut_100"] = 14.;
       upperLimitsExpected["HTlep_2ltau_offZ_cut_150"] = 6.4;
       upperLimitsExpected["HTlep_2ltau_offZ_cut_200"] = 3.6;
       upperLimitsExpected["HTlep_2ltau_offZ_cut_300"] = 1.5;
       upperLimitsExpected["HTlep_3l_onZ_cut_0"] = 33.;
       upperLimitsExpected["HTlep_3l_onZ_cut_100"] = 25.;
       upperLimitsExpected["HTlep_3l_onZ_cut_150"] = 12.;
       upperLimitsExpected["HTlep_3l_onZ_cut_200"] = 6.5;
       upperLimitsExpected["HTlep_3l_onZ_cut_300"] = 3.1;
       upperLimitsExpected["HTlep_2ltau_onZ_cut_0"] = 94.;
       upperLimitsExpected["HTlep_2ltau_onZ_cut_100"] = 61.;
       upperLimitsExpected["HTlep_2ltau_onZ_cut_150"] = 9.9;
       upperLimitsExpected["HTlep_2ltau_onZ_cut_200"] = 4.5;
       upperLimitsExpected["HTlep_2ltau_onZ_cut_300"] = 1.9;
       upperLimitsExpected["METStrong_3l_offZ_cut_0"] = 3.1;
       upperLimitsExpected["METStrong_3l_offZ_cut_50"] = 2.4;
       upperLimitsExpected["METStrong_3l_offZ_cut_75"] = 2.3;
       upperLimitsExpected["METStrong_2ltau_offZ_cut_0"] = 4.8;
       upperLimitsExpected["METStrong_2ltau_offZ_cut_50"] = 3.3;
       upperLimitsExpected["METStrong_2ltau_offZ_cut_75"] = 2.1;
       upperLimitsExpected["METStrong_3l_onZ_cut_20"] = 8.7;
       upperLimitsExpected["METStrong_3l_onZ_cut_50"] = 4.9;
       upperLimitsExpected["METStrong_3l_onZ_cut_75"] = 3.8;
       upperLimitsExpected["METStrong_2ltau_onZ_cut_20"] = 7.3;
       upperLimitsExpected["METStrong_2ltau_onZ_cut_50"] = 2.8;
       upperLimitsExpected["METStrong_2ltau_onZ_cut_75"] = 1.5;
       upperLimitsExpected["METWeak_3l_offZ_cut_0"] = 10.;
       upperLimitsExpected["METWeak_3l_offZ_cut_50"] = 4.7;
       upperLimitsExpected["METWeak_3l_offZ_cut_75"] = 3.0;
       upperLimitsExpected["METWeak_2ltau_offZ_cut_0"] = 21.;
       upperLimitsExpected["METWeak_2ltau_offZ_cut_50"] = 4.0;
       upperLimitsExpected["METWeak_2ltau_offZ_cut_75"] = 2.6;
       upperLimitsExpected["METWeak_3l_onZ_cut_20"] = 30.;
       upperLimitsExpected["METWeak_3l_onZ_cut_50"] = 10.;
       upperLimitsExpected["METWeak_3l_onZ_cut_75"] = 5.4;
       upperLimitsExpected["METWeak_2ltau_onZ_cut_20"] = 88.;
       upperLimitsExpected["METWeak_2ltau_onZ_cut_50"] = 5.5;
       upperLimitsExpected["METWeak_2ltau_onZ_cut_75"] = 2.2;
       upperLimitsExpected["Meff_3l_offZ_cut_0"] = 11.;
       upperLimitsExpected["Meff_3l_offZ_cut_150"] = 8.8;
       upperLimitsExpected["Meff_3l_offZ_cut_300"] = 3.7;
       upperLimitsExpected["Meff_3l_offZ_cut_500"] = 2.1;
       upperLimitsExpected["Meff_2ltau_offZ_cut_0"] = 23.;
       upperLimitsExpected["Meff_2ltau_offZ_cut_150"] = 13.;
       upperLimitsExpected["Meff_2ltau_offZ_cut_300"] = 4.9;
       upperLimitsExpected["Meff_2ltau_offZ_cut_500"] = 2.4;
       upperLimitsExpected["Meff_3l_onZ_cut_0"] = 33.;
       upperLimitsExpected["Meff_3l_onZ_cut_150"] = 25.;
       upperLimitsExpected["Meff_3l_onZ_cut_300"] = 9.;
       upperLimitsExpected["Meff_3l_onZ_cut_500"] = 3.9;
       upperLimitsExpected["Meff_2ltau_onZ_cut_0"] = 94.;
       upperLimitsExpected["Meff_2ltau_onZ_cut_150"] = 35.;
       upperLimitsExpected["Meff_2ltau_onZ_cut_300"] = 6.8;
       upperLimitsExpected["Meff_2ltau_onZ_cut_500"] = 2.5;
       upperLimitsExpected["MeffStrong_3l_offZ_cut_0"] = 3.9;
       upperLimitsExpected["MeffStrong_3l_offZ_cut_150"] = 3.9;
       upperLimitsExpected["MeffStrong_3l_offZ_cut_300"] = 3.0;
       upperLimitsExpected["MeffStrong_3l_offZ_cut_500"] = 2.0;
       upperLimitsExpected["MeffStrong_2ltau_offZ_cut_0"] = 3.8;
       upperLimitsExpected["MeffStrong_2ltau_offZ_cut_150"] = 3.9;
       upperLimitsExpected["MeffStrong_2ltau_offZ_cut_300"] = 3.1;
       upperLimitsExpected["MeffStrong_2ltau_offZ_cut_500"] = 1.6;
       upperLimitsExpected["MeffStrong_3l_onZ_cut_0"] = 6.9;
       upperLimitsExpected["MeffStrong_3l_onZ_cut_150"] = 7.1;
       upperLimitsExpected["MeffStrong_3l_onZ_cut_300"] = 4.9;
       upperLimitsExpected["MeffStrong_3l_onZ_cut_500"] = 3.0;
       upperLimitsExpected["MeffStrong_2ltau_onZ_cut_0"] = 2.4;
       upperLimitsExpected["MeffStrong_2ltau_onZ_cut_150"] = 2.5;
       upperLimitsExpected["MeffStrong_2ltau_onZ_cut_300"] = 2.0;
       upperLimitsExpected["MeffStrong_2ltau_onZ_cut_500"] = 1.1;
 
       if (observed) return upperLimitsObserved[signal_region];
       else          return upperLimitsExpected[signal_region];
     }
 
 
     /// Function checking if there is an OSSF lepton pair or a combination of 3 leptons with an invariant mass close to the Z mass
     /// @todo Should the reference Z mass be 91.2?
     int isonZ (const Particles& particles)  {
       int onZ = 0;
       double best_mass_2 = 999.;
       double best_mass_3 = 999.;
 
       // Loop over all 2 particle combinations to find invariant mass of OSSF pair closest to Z mass
-      foreach ( const Particle& p1, particles  )  {
-        foreach ( const Particle& p2, particles  )  {
+      for ( const Particle& p1 : particles  )  {
+        for ( const Particle& p2 : particles  )  {
           double mass_difference_2_old = fabs(91.0 - best_mass_2);
           double mass_difference_2_new = fabs(91.0 - (p1.momentum() + p2.momentum()).mass()/GeV);
 
           // If particle combination is OSSF pair calculate mass difference to Z mass
           if ( (p1.pid()*p2.pid() == -121 || p1.pid()*p2.pid() == -169) )  {
 
             // Get invariant mass closest to Z mass
             if (mass_difference_2_new < mass_difference_2_old)
               best_mass_2 = (p1.momentum() + p2.momentum()).mass()/GeV;
 
             // In case there is an OSSF pair take also 3rd lepton into account (e.g. from FSR and photon to electron conversion)
-            foreach ( const Particle & p3 , particles  )  {
+            for ( const Particle & p3 : particles  )  {
               double mass_difference_3_old = fabs(91.0 - best_mass_3);
               double mass_difference_3_new = fabs(91.0 - (p1.momentum() + p2.momentum() + p3.momentum()).mass()/GeV);
               if (mass_difference_3_new < mass_difference_3_old)
                 best_mass_3 = (p1.momentum() + p2.momentum() + p3.momentum()).mass()/GeV;
             }
           }
         }
       }
 
       // Pick the minimum invariant mass of the best OSSF pair combination and the best 3 lepton combination
       // If this mass is in a 20 GeV window around the Z mass, the event is classified as onZ
       double best_mass = min(best_mass_2, best_mass_3);
       if (fabs(91.0 - best_mass) < 20) onZ = 1;
       return onZ;
     }
 
     //@}
 
 
   private:
 
     /// Histograms
     //@{
     Histo1DPtr _h_HTlep_all, _h_HTjets_all, _h_MET_all, _h_Meff_all;
     Histo1DPtr _h_pt_1_3l, _h_pt_2_3l, _h_pt_3_3l, _h_pt_1_2ltau, _h_pt_2_2ltau, _h_pt_3_2ltau;
     Histo1DPtr _h_e_n, _h_mu_n, _h_tau_n;
     Histo1DPtr _h_excluded;
     //@}
 
     /// Fiducial efficiencies to model the effects of the ATLAS detector
     bool _use_fiducial_lepton_efficiency;
 
     /// List of signal regions and event counts per signal region
     vector<string> _signal_regions;
-    map<string, double> _eventCountsPerSR;
+
+    // *** LEIF *** i think this was intended
+    map<string, CounterPtr> _eventCountsPerSR;
 
   };
 
 
 
   DECLARE_RIVET_PLUGIN(ATLAS_2012_I1204447);
 
 }
diff --git a/analyses/pluginATLAS/ATLAS_2013_I1219109.cc b/analyses/pluginATLAS/ATLAS_2013_I1219109.cc
--- a/analyses/pluginATLAS/ATLAS_2013_I1219109.cc
+++ b/analyses/pluginATLAS/ATLAS_2013_I1219109.cc
@@ -1,146 +1,147 @@
 // -*- C++ -*-
 #include "Rivet/Analysis.hh"
 #include "Rivet/Projections/FinalState.hh"
 #include "Rivet/Projections/WFinder.hh"
 #include "Rivet/Projections/VetoedFinalState.hh"
 #include "Rivet/Projections/FastJets.hh"
 #include "Rivet/Projections/HeavyHadrons.hh"
 
 namespace Rivet {
 
 
   /// @brief ATLAS W+b measurement
   class ATLAS_2013_I1219109: public Analysis {
   public:
 
     ///@brief: Electroweak Wjj production at 8 TeV
     DEFAULT_RIVET_ANALYSIS_CTOR(ATLAS_2013_I1219109);
     //@}
 
     void init() {
 
       // Get options from the new option system
       _mode = 0;
       if ( getOption("LMODE") == "EL" ) _mode = 1;
       if ( getOption("LMODE") == "MU" ) _mode = 2;
 
       const FinalState fs;
 
       Cut cuts = Cuts::abseta < 2.5 && Cuts::pT >= 25*GeV;
 
       // W finder for electrons and muons
       WFinder wf_mu(fs, cuts, PID::MUON, 0.0*GeV, DBL_MAX, 0.0, 0.1,
                  WFinder::ChargedLeptons::PROMPT, WFinder::ClusterPhotons::NODECAY, WFinder::AddPhotons::NO, WFinder::MassWindow::MT);
       WFinder wf_el(fs, cuts, PID::ELECTRON, 0.0*GeV, DBL_MAX, 0.0, 0.1,
                  WFinder::ChargedLeptons::PROMPT, WFinder::ClusterPhotons::NODECAY, WFinder::AddPhotons::NO, WFinder::MassWindow::MT);
       declare(wf_mu, "WFmu");
       declare(wf_el, "WFel");
 
       // jets
       VetoedFinalState jet_fs(fs);
       jet_fs.addVetoOnThisFinalState(wf_el);
       jet_fs.addVetoOnThisFinalState(wf_mu);
       FastJets fj(jet_fs, FastJets::ANTIKT, 0.4);
       fj.useInvisibles();
       declare(fj, "Jets");
       declare(HeavyHadrons(Cuts::abseta < 2.5 && Cuts::pT > 5*GeV), "BHadrons");
 
 
       // book histograms
-      book(_njet     ,1, 1); // dSigma / dNjet
-      book(_jet1_bPt ,3, 1); // dSigma / dBjetPt for Njet = 1
-      book(_jet2_bPt ,8, 1); // dSigma / dBjetPt for Njet = 2
+      // *** LEIF *** where did the y02 histos go?
+      book(_njet     ,1, 1, 1); // dSigma / dNjet
+      book(_jet1_bPt ,3, 1, 1); // dSigma / dBjetPt for Njet = 1
+      book(_jet2_bPt ,8, 1, 1); // dSigma / dBjetPt for Njet = 2
 
     }
 
 
     void analyze(const Event& event) {
 
       //  retrieve W boson candidate
       const WFinder& wf_mu = apply<WFinder>(event, "WFmu");
       const WFinder& wf_el = apply<WFinder>(event, "WFel");
 
       size_t nWmu = wf_mu.size();
       size_t nWel = wf_el.size();
 
       if (_mode == 0 && !((nWmu == 1 && !nWel) || (!nWmu && nWel == 1)))  vetoEvent; // one W->munu OR W->elnu candidate, otherwise veto
       if (_mode == 1 && !(!nWmu && nWel == 1))  vetoEvent; // one W->elnu candidate, otherwise veto
       if (_mode == 2 && !(nWmu == 1 && !nWel))  vetoEvent; // one W->munu candidate, otherwise veto
 
 
       if (   (nWmu? wf_mu : wf_el).bosons().size() != 1 )  vetoEvent; // only one W boson candidate
       if ( !((nWmu? wf_mu : wf_el).mT() > 60.0*GeV) )      vetoEvent;
       //const Particle& Wboson  = wf.boson();
 
 
       // retrieve constituent neutrino
       const Particle& neutrino = (nWmu? wf_mu : wf_el).constituentNeutrino();
       if( !(neutrino.pT() > 25*GeV) )  vetoEvent;
 
       // retrieve constituent lepton
       const Particle& lepton = (nWmu? wf_mu : wf_el).constituentLepton();
 
       // count good jets, check if good jet contains B hadron
       const Particles& bHadrons = apply<HeavyHadrons>(event, "BHadrons").bHadrons();
       const Jets& jets = apply<JetAlg>(event, "Jets").jetsByPt(25*GeV);
       int goodjets = 0, bjets = 0;
       double bPt = 0.;
       for(const Jet& j : jets) {
         if( (j.abseta() < 2.1) && (deltaR(lepton, j) > 0.5) ) {
           // this jet passes the selection!
           ++goodjets;
           // j.bTagged() uses ghost association which is
           // more elegant, but not what has been used in
           // this analysis originally, will match B had-
           // rons in eta-phi space instead
           for(const Particle& b : bHadrons) {
             if( deltaR(j, b) < 0.3 ) {
               // jet matched to B hadron!
               if(!bPt)  bPt = j.pT() * GeV; // leading b-jet pT
               ++bjets; // count number of b-jets
               break;
             }
           }
         }
       }
       if( goodjets > 2 )  vetoEvent; // at most two jets
       if( !bjets )  vetoEvent; // at least one of them b-tagged
 
       double njets = double(goodjets);
       double ncomb = 3.0;
       _njet->fill(njets);
       _njet->fill(ncomb);
 
       if(     goodjets == 1)  _jet1_bPt->fill(bPt);
       else if(goodjets == 2)  _jet2_bPt->fill(bPt);
     }
 
 
     void finalize() {
       const double sf = _mode? 1.0 : 0.5;
       const double xs_pb = sf * crossSection() / picobarn  / sumOfWeights();
       const double xs_fb = sf * crossSection() / femtobarn / sumOfWeights();
       scale(_njet,     xs_pb);
       scale(_jet1_bPt, xs_fb);
       scale(_jet2_bPt, xs_fb);
     }
 
   protected:
 
     size_t _mode;
 
   private:
 
     Histo1DPtr _njet;
     Histo1DPtr _jet1_bPt;
     Histo1DPtr _jet2_bPt;
 
     //bool _isMuon;
 
   };
 
 
   // The hook for the plugin system
   DECLARE_RIVET_PLUGIN(ATLAS_2013_I1219109);
 
 }
diff --git a/analyses/pluginATLAS/ATLAS_2014_I1306615.cc b/analyses/pluginATLAS/ATLAS_2014_I1306615.cc
--- a/analyses/pluginATLAS/ATLAS_2014_I1306615.cc
+++ b/analyses/pluginATLAS/ATLAS_2014_I1306615.cc
@@ -1,436 +1,436 @@
 // -*- C++ -*-
 #include "Rivet/Analysis.hh"
 #include "Rivet/Projections/FinalState.hh"
 #include "Rivet/Projections/PromptFinalState.hh"
 #include "Rivet/Projections/DressedLeptons.hh"
 #include "Rivet/Projections/VetoedFinalState.hh"
 #include "Rivet/Projections/FastJets.hh"
 
 namespace Rivet {
 
 
   /// @brief ATLAS H->yy differential cross-sections measurement
   ///
   /// @author Michaela Queitsch-Maitland <michaela.queitsch-maitland@cern.ch>
   //
   // arXiv: http://arxiv.org/abs/ARXIV:1407.4222
   // HepData: http://hepdata.cedar.ac.uk/view/ins1306615
   class ATLAS_2014_I1306615 : public Analysis {
   public:
 
     // Constructor
     ATLAS_2014_I1306615()
       : Analysis("ATLAS_2014_I1306615")
     {    }
 
 
     // Book histograms and initialise projections before the run
     void init() {
 
       // Final state
       // All particles within |eta| < 5.0
       const FinalState FS(Cuts::abseta<5.0);
       declare(FS,"FS");
 
       // Project photons with pT > 25 GeV and |eta| < 2.37
       PromptFinalState ph_FS(Cuts::abseta<2.37 && Cuts::pT>25*GeV);
       declare(ph_FS, "PH_FS");
 
       // Project photons for dressing
       FinalState ph_dressing_FS(Cuts::abspid == PID::PHOTON);
 
       // Project bare electrons
       PromptFinalState el_bare_FS(Cuts::abseta < 5.0 && Cuts::abspid == PID::ELECTRON);
 
       // Project dressed electrons with pT > 15 GeV and |eta| < 2.47
       DressedLeptons el_dressed_FS(ph_dressing_FS, el_bare_FS, 0.1, Cuts::abseta < 2.47 && Cuts::pT > 15*GeV);
       declare(el_dressed_FS,"EL_DRESSED_FS");
 
       // Project bare muons
       PromptFinalState mu_bare_FS(Cuts::abseta < 5.0 && Cuts::abspid == PID::MUON);
 
       // Project dressed muons with pT > 15 GeV and |eta| < 2.47
       //DressedLeptons mu_dressed_FS(ph_dressing_FS, mu_bare_FS, 0.1, true, -2.47, 2.47, 15.0*GeV, false);
       DressedLeptons mu_dressed_FS(ph_dressing_FS, mu_bare_FS, 0.1, Cuts::abseta < 2.47 && Cuts::pT > 15*GeV);
       declare(mu_dressed_FS,"MU_DRESSED_FS");
 
       // Final state excluding muons and neutrinos (for jet building and photon isolation)
       VetoedFinalState veto_mu_nu_FS(FS);
       veto_mu_nu_FS.vetoNeutrinos();
       veto_mu_nu_FS.addVetoPairId(PID::MUON);
       declare(veto_mu_nu_FS, "VETO_MU_NU_FS");
 
       // Build the anti-kT R=0.4 jets, using FinalState particles (vetoing muons and neutrinos)
       FastJets jets(veto_mu_nu_FS, FastJets::ANTIKT, 0.4);
       declare(jets, "JETS");
 
       // Book histograms
       // 1D distributions
       book(_h_pT_yy         ,1,1,1);
       book(_h_y_yy          ,2,1,1);
       book(_h_Njets30       ,3,1,1);
       book(_h_Njets50       ,4,1,1);
       book(_h_pT_j1         ,5,1,1);
       book(_h_y_j1          ,6,1,1);
       book(_h_HT            ,7,1,1);
       book(_h_pT_j2         ,8,1,1);
       book(_h_Dy_jj         ,9,1,1);
       book(_h_Dphi_yy_jj    ,10,1,1);
       book(_h_cosTS_CS      ,11,1,1);
       book(_h_cosTS_CS_5bin ,12,1,1);
       book(_h_Dphi_jj       ,13,1,1);
       book(_h_pTt_yy        ,14,1,1);
       book(_h_Dy_yy         ,15,1,1);
       book(_h_tau_jet       ,16,1,1);
       book(_h_sum_tau_jet   ,17,1,1);
       book(_h_y_j2          ,18,1,1);
       book(_h_pT_j3         ,19,1,1);
       book(_h_m_jj          ,20,1,1);
       book(_h_pT_yy_jj      ,21,1,1);
 
       // 2D distributions of cosTS_CS x pT_yy
       book(_h_cosTS_pTyy_low,  22,1,1);
       book(_h_cosTS_pTyy_high, 22,1,2);
       book(_h_cosTS_pTyy_rest, 22,1,3);
 
       // 2D distributions of Njets x pT_yy
       book(_h_pTyy_Njets0, 23,1,1);
       book(_h_pTyy_Njets1, 23,1,2);
       book(_h_pTyy_Njets2, 23,1,3);
 
       book(_h_pTj1_excl, 24,1,1);
 
       // Fiducial regions
       book(_h_fidXSecs, 30,1,1);
     }
 
     // Perform the per-event analysis
     void analyze(const Event& event) {
 
       // Get final state particles
       const Particles& FS_ptcls         = apply<FinalState>(event, "FS").particles();
       const Particles& ptcls_veto_mu_nu = apply<VetoedFinalState>(event, "VETO_MU_NU_FS").particles();
       const Particles& photons          = apply<PromptFinalState>(event, "PH_FS").particlesByPt();
       vector<DressedLepton> good_el          = apply<DressedLeptons>(event, "EL_DRESSED_FS").dressedLeptons();
       vector<DressedLepton> good_mu          = apply<DressedLeptons>(event, "MU_DRESSED_FS").dressedLeptons();
 
       // For isolation calculation
       float dR_iso    = 0.4;
       float ETcut_iso = 14.0;
       FourMomentum ET_iso;
 
       // Fiducial selection: pT > 25 GeV, |eta| < 2.37 and isolation (in cone deltaR = 0.4) is < 14 GeV
       Particles fid_photons;
       for (const Particle& ph : photons) {
 
         // Calculate isolation
         ET_iso = - ph.momentum();
         // Loop over fs truth particles (excluding muons and neutrinos)
         for (const Particle& p : ptcls_veto_mu_nu) {
           // Check if the truth particle is in a cone of 0.4
           if ( deltaR(ph, p) < dR_iso ) ET_iso += p.momentum();
         }
 
         // Check isolation
         if ( ET_iso.Et() > ETcut_iso ) continue;
 
         // Fill vector of photons passing fiducial selection
         fid_photons.push_back(ph);
       }
 
       if (fid_photons.size() < 2)  vetoEvent;
 
       const FourMomentum y1 = fid_photons[0].momentum();
       const FourMomentum y2 = fid_photons[1].momentum();
 
       double m_yy = (y1 + y2).mass();
 
       // Relative pT cuts
       if ( y1.pT() < 0.35 * m_yy || y2.pT() < 0.25 * m_yy ) vetoEvent;
 
       // Mass window cut
       if ( m_yy < 105 || m_yy > 160 ) vetoEvent;
 
       // -------------------------------------------- //
       // Passed diphoton baseline fiducial selection! //
       // -------------------------------------------- //
 
       // Muon and Electron selection
       ifilter_discard(good_mu, [&](const DressedLepton& lep) { return deltaR(lep, y1) < 0.4 || deltaR(lep, y2) < 0.4; });
       ifilter_discard(good_el, [&](const DressedLepton& lep) { return deltaR(lep, y1) < 0.4 || deltaR(lep, y2) < 0.4; });
 
       // Find prompt, invisible particles for missing ET calculation
       // Based on VisibleFinalState projection
       FourMomentum invisible(0,0,0,0);
-      foreach (const Particle& p, FS_ptcls) {
+      for (const Particle& p : FS_ptcls) {
 
         // Veto non-prompt particles (from hadron or tau decay)
         if ( !p.isPrompt() ) continue;
         // Charged particles are visible
-        if ( PID::threeCharge( p.pid() ) != 0 ) continue;
+        if ( PID::charge3( p.pid() ) != 0 ) continue;
         // Neutral hadrons are visible
         if ( PID::isHadron( p.pid() ) ) continue;
         // Photons are visible
         if ( p.pid() == PID::PHOTON ) continue;
         // Gluons are visible (for parton level analyses)
         if ( p.pid() == PID::GLUON ) continue;
         // Everything else is invisible
         invisible += p.momentum();
       }
       double MET = invisible.Et();
 
       // Jet selection
       // Get jets with pT > 25 GeV and |rapidity| < 4.4
       //const Jets& jets = apply<FastJets>(event, "JETS").jetsByPt(25.0*GeV, MAXDOUBLE, -4.4, 4.4, RAPIDITY);
       const Jets& jets = apply<FastJets>(event, "JETS").jetsByPt(Cuts::pT>25*GeV && Cuts::absrap <4.4);
 
       Jets jets_25, jets_30, jets_50;
 
       for (const Jet& jet : jets) {
 
         bool passOverlap = true;
         // Overlap with leading photons
         if ( deltaR(y1, jet.momentum()) < 0.4 ) passOverlap = false;
         if ( deltaR(y2, jet.momentum()) < 0.4 ) passOverlap = false;
 
         // Overlap with good electrons
         for (const auto& el : good_el) {
           if ( deltaR(el, jet) < 0.2 ) passOverlap = false;
         }
 
         if ( ! passOverlap ) continue;
 
         if ( jet.abseta() < 2.4 || ( jet.abseta() > 2.4 && jet.pT() > 30*GeV) ) jets_25 += jet;
         if ( jet.pT() > 30*GeV ) jets_30 += jet;
         if ( jet.pT() > 50*GeV ) jets_50 += jet;
       }
 
       // Fiducial regions
       _h_fidXSecs->fill(1);
       if ( jets_30.size() >= 1 ) _h_fidXSecs->fill(2);
       if ( jets_30.size() >= 2 ) _h_fidXSecs->fill(3);
       if ( jets_30.size() >= 3 ) _h_fidXSecs->fill(4);
-      if ( jets_30.size() >= 2 && passVBFCuts(y1 + y2, jets_30.at(0)->momentum(), jets_30.at(1)->momentum()) ) _h_fidXSecs->fill(5);
+      if ( jets_30.size() >= 2 && passVBFCuts(y1 + y2, jets_30.at(0).momentum(), jets_30.at(1).momentum()) ) _h_fidXSecs->fill(5);
       if ( (good_el.size() + good_mu.size()) > 0 ) _h_fidXSecs->fill(6);
       if ( MET > 80 ) _h_fidXSecs->fill(7);
 
       // Fill histograms
       // Inclusive variables
       _pT_yy    = (y1 + y2).pT();
       _y_yy     = (y1 + y2).absrap();
       _cosTS_CS = cosTS_CS(y1, y2);
       _pTt_yy   = pTt(y1, y2);
       _Dy_yy    = fabs( deltaRap(y1, y2) );
 
       _Njets30 = jets_30.size() > 3 ? 3 : jets_30.size();
       _Njets50 = jets_50.size() > 3 ? 3 : jets_50.size();
       _h_Njets30->fill(_Njets30);
       _h_Njets50->fill(_Njets50);
 
       _pT_j1 = jets_30.size() > 0 ? jets_30[0].momentum().pT() : 0.;
       _pT_j2 = jets_30.size() > 1 ? jets_30[1].momentum().pT() : 0.;
       _pT_j3 = jets_30.size() > 2 ? jets_30[2].momentum().pT() : 0.;
 
       _HT = 0.0;
       for (const Jet& jet : jets_30) {  _HT += jet.pT(); }
 
       _tau_jet     = tau_jet_max(y1 + y2, jets_25);
       _sum_tau_jet = sum_tau_jet(y1 + y2, jets_25);
 
       _h_pT_yy        ->fill(_pT_yy);
       _h_y_yy         ->fill(_y_yy);
       _h_pT_j1        ->fill(_pT_j1);
       _h_cosTS_CS     ->fill(_cosTS_CS);
       _h_cosTS_CS_5bin->fill(_cosTS_CS);
       _h_HT           ->fill(_HT);
       _h_pTt_yy       ->fill(_pTt_yy);
       _h_Dy_yy        ->fill(_Dy_yy);
       _h_tau_jet      ->fill(_tau_jet);
       _h_sum_tau_jet  ->fill(_sum_tau_jet);
 
       // >=1 jet variables
       if ( jets_30.size() >= 1 ) {
         FourMomentum j1 = jets_30[0].momentum();
         _y_j1 = j1.absrap();
 
 	_h_pT_j2->fill(_pT_j2);
 	_h_y_j1 ->fill(_y_j1);
       }
 
       // >=2 jet variables
       if ( jets_30.size() >= 2 ) {
         FourMomentum j1 = jets_30[0].momentum();
         FourMomentum j2 = jets_30[1].momentum();
 
         _Dy_jj      = fabs( deltaRap(j1, j2) );
         _Dphi_jj    = fabs( deltaPhi(j1, j2) );
         _Dphi_yy_jj = fabs( deltaPhi(y1 + y2, j1 + j2) );
         _m_jj       = (j1 + j2).mass();
         _pT_yy_jj   = (y1 + y2 + j1 + j2).pT();
         _y_j2       = j2.absrap();
 
 	_h_Dy_jj      ->fill(_Dy_jj);
 	_h_Dphi_jj    ->fill(_Dphi_jj);
 	_h_Dphi_yy_jj ->fill(_Dphi_yy_jj);
 	_h_m_jj       ->fill(_m_jj);
 	_h_pT_yy_jj   ->fill(_pT_yy_jj);
 	_h_pT_j3      ->fill(_pT_j3);
 	_h_y_j2       ->fill(_y_j2);
       }
 
       // 2D distributions of cosTS_CS x pT_yy
       if ( _pT_yy < 80 )
 	_h_cosTS_pTyy_low->fill(_cosTS_CS);
       else if ( _pT_yy > 80 && _pT_yy < 200 )
 	_h_cosTS_pTyy_high->fill(_cosTS_CS);
       else if ( _pT_yy > 200 )
 	_h_cosTS_pTyy_rest->fill(_cosTS_CS);
 
       // 2D distributions of pT_yy x Njets
       if ( _Njets30 == 0 )
 	_h_pTyy_Njets0->fill(_pT_yy);
       else if ( _Njets30 == 1 )
 	_h_pTyy_Njets1->fill(_pT_yy);
       else if ( _Njets30 >= 2 )
 	_h_pTyy_Njets2->fill(_pT_yy);
 
       if ( _Njets30 == 1 ) _h_pTj1_excl->fill(_pT_j1);
 
     }
 
     // Normalise histograms after the run
     void finalize() {
 
       const double xs = crossSectionPerEvent()/femtobarn;
 
       scale(_h_pT_yy, xs);
       scale(_h_y_yy, xs);
       scale(_h_pT_j1, xs);
       scale(_h_y_j1, xs);
       scale(_h_HT, xs);
       scale(_h_pT_j2, xs);
       scale(_h_Dy_jj, xs);
       scale(_h_Dphi_yy_jj, xs);
       scale(_h_cosTS_CS, xs);
       scale(_h_cosTS_CS_5bin, xs);
       scale(_h_Dphi_jj, xs);
       scale(_h_pTt_yy, xs);
       scale(_h_Dy_yy, xs);
       scale(_h_tau_jet, xs);
       scale(_h_sum_tau_jet, xs);
       scale(_h_y_j2, xs);
       scale(_h_pT_j3, xs);
       scale(_h_m_jj, xs);
       scale(_h_pT_yy_jj, xs);
       scale(_h_cosTS_pTyy_low, xs);
       scale(_h_cosTS_pTyy_high, xs);
       scale(_h_cosTS_pTyy_rest, xs);
       scale(_h_pTyy_Njets0, xs);
       scale(_h_pTyy_Njets1, xs);
       scale(_h_pTyy_Njets2, xs);
       scale(_h_pTj1_excl, xs);
       scale(_h_Njets30, xs);
       scale(_h_Njets50, xs);
       scale(_h_fidXSecs, xs);
     }
 
     // VBF-enhanced dijet topology selection cuts
     bool passVBFCuts(const FourMomentum &H, const FourMomentum &j1, const FourMomentum &j2) {
       return ( fabs(deltaRap(j1, j2)) > 2.8 && (j1 + j2).mass() > 400 && fabs(deltaPhi(H, j1 + j2)) > 2.6 );
     }
 
     // Cosine of the decay angle in the Collins-Soper frame
     double cosTS_CS(const FourMomentum &y1, const FourMomentum &y2) {
       return fabs( ( (y1.E() + y1.pz())* (y2.E() - y2.pz()) - (y1.E() - y1.pz()) * (y2.E() + y2.pz()) )
 		   / ((y1 + y2).mass() * sqrt(pow((y1 + y2).mass(), 2) + pow((y1 + y2).pt(), 2)) ) );
     }
 
     // Diphoton pT along thrust axis
     double pTt(const FourMomentum &y1, const FourMomentum &y2) {
       return fabs(y1.px() * y2.py() - y2.px() * y1.py()) / (y1 - y2).pT()*2;
     }
 
     // Tau of jet  (see paper for description)
     // tau_jet = mT/(2*cosh(y*)), where mT = pT (+) m, and y* = rapidty in Higgs rest frame
     double tau_jet( const FourMomentum &H, const FourMomentum &jet ) {
       return sqrt( pow(jet.pT(),2) + pow(jet.mass(),2) ) / (2.0 * cosh( jet.rapidity() - H.rapidity() ) );
     }
 
     // Maximal (leading) tau_jet (see paper for description)
     double tau_jet_max(const FourMomentum &H, const Jets& jets, double tau_jet_cut = 8.) {
       double max_tj = 0;
       for (const auto& jet : jets) {
         FourMomentum j = jet.momentum();
         if (tau_jet(H, j) > tau_jet_cut)  max_tj = max(tau_jet(H, j), max_tj);
       }
       return max_tj;
     }
 
     // Scalar sum of tau for all jets (see paper for description)
     double sum_tau_jet(const FourMomentum &H, const Jets& jets, double tau_jet_cut = 8.)  {
       double sum_tj = 0;
       for (const auto& jet : jets) {
         FourMomentum j = jet.momentum();
         if (tau_jet(H, j) > tau_jet_cut)  sum_tj += tau_jet(H, j);
       }
       return sum_tj;
     }
 
   private:
 
     Histo1DPtr _h_pT_yy;
     Histo1DPtr _h_y_yy;
     Histo1DPtr _h_Njets30;
     Histo1DPtr _h_Njets50;
     Histo1DPtr _h_pT_j1;
     Histo1DPtr _h_y_j1;
     Histo1DPtr _h_HT;
     Histo1DPtr _h_pT_j2;
     Histo1DPtr _h_Dy_jj;
     Histo1DPtr _h_Dphi_yy_jj;
     Histo1DPtr _h_cosTS_CS;
     Histo1DPtr _h_cosTS_CS_5bin;
     Histo1DPtr _h_Dphi_jj;
     Histo1DPtr _h_pTt_yy;
     Histo1DPtr _h_Dy_yy;
     Histo1DPtr _h_tau_jet;
     Histo1DPtr _h_sum_tau_jet;
     Histo1DPtr _h_y_j2;
     Histo1DPtr _h_pT_j3;
     Histo1DPtr _h_m_jj;
     Histo1DPtr _h_pT_yy_jj;
     Histo1DPtr _h_cosTS_pTyy_low;
     Histo1DPtr _h_cosTS_pTyy_high;
     Histo1DPtr _h_cosTS_pTyy_rest;
     Histo1DPtr _h_pTyy_Njets0;
     Histo1DPtr _h_pTyy_Njets1;
     Histo1DPtr _h_pTyy_Njets2;
     Histo1DPtr _h_pTj1_excl;
     Histo1DPtr _h_fidXSecs;
 
     int _Njets30;
     int _Njets50;
     double _pT_yy;
     double _y_yy;
     double _cosTS_CS;
     double _pT_j1;
     double _m_jj;
     double _y_j1;
     double _HT;
     double _pT_j2;
     double _y_j2;
     double _Dphi_yy_jj;
     double _pT_yy_jj;
     double _Dphi_jj;
     double _Dy_jj;
     double _pT_j3;
     double _pTt_yy;
     double _Dy_yy;
     double _tau_jet;
     double _sum_tau_jet;
   };
 
 
   DECLARE_RIVET_PLUGIN(ATLAS_2014_I1306615);
 
 }
diff --git a/analyses/pluginATLAS/ATLAS_2014_I1319490.cc b/analyses/pluginATLAS/ATLAS_2014_I1319490.cc
--- a/analyses/pluginATLAS/ATLAS_2014_I1319490.cc
+++ b/analyses/pluginATLAS/ATLAS_2014_I1319490.cc
@@ -1,221 +1,221 @@
 #include "Rivet/Analysis.hh"
 #include "Rivet/Projections/FinalState.hh"
 #include "Rivet/Projections/WFinder.hh"
 #include "Rivet/Projections/FastJets.hh"
 #include "Rivet/Projections/VetoedFinalState.hh"
 
 namespace Rivet {
 
 
   ///@brief Electroweak Wjj production at 8 TeV
   class ATLAS_2014_I1319490 : public Analysis {
   public:
 
     DEFAULT_RIVET_ANALYSIS_CTOR(ATLAS_2014_I1319490);
 
 
     // Book histograms and initialise projections before the run
     void init() {
 
      // Get options from the new option system
       _mode = 0;
       if ( getOption("LMODE") == "EL" ) _mode = 1;
       if ( getOption("LMODE") == "MU" ) _mode = 2;
 
       FinalState fs;
 
       Cut cuts;
       if (_mode == 2) { // muon channel
         cuts = (Cuts::pT > 25.0*GeV) & Cuts::etaIn(-2.4, 2.4);
       } else if (_mode) { // electron channel
         cuts = (Cuts::pT > 25.0*GeV) & ( Cuts::etaIn(-2.47, -1.52) | Cuts::etaIn(-1.37, 1.37) | Cuts::etaIn(1.52, 2.47) );
       } else { // combined data extrapolated to common phase space
         cuts = (Cuts::pT > 25.0*GeV) & Cuts::etaIn(-2.5, 2.5);
       }
 
       // bosons
-      WFinder wfinder_mu(fs, cuts, PID::MUON, 40.0*GeV, MAXDOUBLE, 0.0*GeV, 0.1,
+      WFinder wfinder_mu(fs, cuts, PID::MUON, 40.0*GeV, YODA::MAXDOUBLE, 0.0*GeV, 0.1,
                       WFinder::ChargedLeptons::PROMPT, WFinder::ClusterPhotons::NODECAY, WFinder::AddPhotons::NO, WFinder::MassWindow::MT);
       declare(wfinder_mu, "WFmu");
-      WFinder wfinder_el(fs, cuts, PID::ELECTRON, 40.0*GeV, MAXDOUBLE, 0.0*GeV, 0.1,
+      WFinder wfinder_el(fs, cuts, PID::ELECTRON, 40.0*GeV, YODA::MAXDOUBLE, 0.0*GeV, 0.1,
                       WFinder::ChargedLeptons::PROMPT, WFinder::ClusterPhotons::NODECAY, WFinder::AddPhotons::NO, WFinder::MassWindow::MT);
       declare(wfinder_el, "WFel");
 
       // jets
       VetoedFinalState jet_fs(fs);
       //jet_fs.addVetoOnThisFinalState(getProjection<WFinder>("WF"));
       jet_fs.addVetoOnThisFinalState(wfinder_mu);
       jet_fs.addVetoOnThisFinalState(wfinder_el);
       FastJets jets(jet_fs, FastJets::ANTIKT, 0.4, JetAlg::Muons::ALL, JetAlg::Invisibles::DECAY);
       declare(jets, "Jets");
 
       // book histograms
       book(histos["h_N_incl"]            ,1,1,_mode+1);
       book(histos["h_N"]                 ,4,1,_mode+1);
       book(histos["h_pt_jet1_1jet"]      ,5,1,_mode+1);
       book(histos["h_pt_jet1_1jet_excl"] ,6,1,_mode+1);
       book(histos["h_pt_jet1_2jet"]      ,7,1,_mode+1);
       book(histos["h_pt_jet1_3jet"]      ,8,1,_mode+1);
       book(histos["h_pt_jet2_2jet"]      ,9,1,_mode+1);
       book(histos["h_pt_jet3_3jet"]      ,10,1,_mode+1);
       book(histos["h_pt_jet4_4jet"]      ,11,1,_mode+1);
       book(histos["h_pt_jet5_5jet"]      ,12,1,_mode+1);
       book(histos["h_y_jet1_1jet"]       ,13,1,_mode+1);
       book(histos["h_y_jet2_2jet"]       ,14,1,_mode+1);
       book(histos["h_HT_1jet"]           ,15,1,_mode+1);
       book(histos["h_HT_1jet_excl"]      ,16,1,_mode+1);
       book(histos["h_HT_2jet"]           ,17,1,_mode+1);
       book(histos["h_HT_2jet_excl"]      ,18,1,_mode+1);
       book(histos["h_HT_3jet"]           ,19,1,_mode+1);
       book(histos["h_HT_3jet_excl"]      ,20,1,_mode+1);
       book(histos["h_HT_4jet"]           ,21,1,_mode+1);
       book(histos["h_HT_5jet"]           ,22,1,_mode+1);
       book(histos["h_deltaPhi_jet12"]    ,23,1,_mode+1);
       book(histos["h_deltaRap_jet12"]    ,24,1,_mode+1);
       book(histos["h_deltaR_jet12"]      ,25,1,_mode+1);
       book(histos["h_M_Jet12_2jet"]      ,26,1,_mode+1);
       book(histos["h_y_jet3_3jet"]       ,27,1,_mode+1);
       book(histos["h_y_jet4_4jet"]       ,28,1,_mode+1);
       book(histos["h_y_jet5_5jet"]       ,29,1,_mode+1);
       book(histos["h_ST_1jet"]           ,30,1,_mode+1);
       book(histos["h_ST_2jet"]           ,31,1,_mode+1);
       book(histos["h_ST_2jet_excl"]      ,32,1,_mode+1);
       book(histos["h_ST_3jet"]           ,33,1,_mode+1);
       book(histos["h_ST_3jet_excl"]      ,34,1,_mode+1);
       book(histos["h_ST_4jet"]           ,35,1,_mode+1);
       book(histos["h_ST_5jet"]           ,36,1,_mode+1);
     }
 
 
     void fillPlots(const Particle& lepton, const double& missET, Jets& all_jets) {
       // do jet-lepton overlap removal
       Jets jets;
       double ST = 0.0; // scalar pT sum of all selected jets
       for (const Jet &j : all_jets) {
         if (deltaR(j, lepton) > 0.5) {
           jets += j;
           ST += j.pT() / GeV;
         }
       }
 
       const size_t njets = jets.size();
 
       const double HT = ST + lepton.pT() / GeV + missET;
 
       histos["h_N"]->fill(njets + 0.5);
       for (size_t i = 0; i <= njets; ++i) {
         histos["h_N_incl"]->fill(i + 0.5);
       }
 
       if (njets) {
         const double pT1  = jets[0].pT() / GeV;
         const double rap1 = jets[0].absrap();
         histos["h_pt_jet1_1jet" ]->fill(pT1);
         histos["h_y_jet1_1jet"]->fill(rap1);
         histos["h_HT_1jet"]->fill(HT);
         histos["h_ST_1jet"]->fill(ST);
         if (njets == 1) {
           histos["h_pt_jet1_1jet_excl"]->fill(pT1);
           histos["h_HT_1jet_excl"]->fill(HT);
         } else {
           const double pT2  = jets[1].pT() / GeV;
           const double rap2 = jets[1].absrap();
           const double dR   = deltaR(jets[0], jets[1]);
           const double dRap = deltaRap(jets[0], jets[1]);
           const double dPhi = deltaPhi(jets[0], jets[1]);
           const double mjj  = (jets[0].momentum() + jets[1].momentum()).mass() / GeV;
           histos["h_pt_jet1_2jet"]->fill(pT1);
           histos["h_pt_jet2_2jet"]->fill(pT2);
           histos["h_y_jet2_2jet"]->fill(rap2);
           histos["h_M_Jet12_2jet"]->fill(mjj);
           histos["h_HT_2jet"]->fill(HT);
           histos["h_ST_2jet"]->fill(ST);
           histos["h_deltaPhi_jet12"]->fill(dPhi);
           histos["h_deltaRap_jet12"]->fill(dRap);
           histos["h_deltaR_jet12"]->fill(dR);
           if (njets == 2) {
             histos["h_ST_2jet_excl"]->fill(ST);
             histos["h_HT_2jet_excl"]->fill(HT);
           } else {
             const double pT3  = jets[2].pT() / GeV;
             const double rap3 = jets[2].absrap();
             histos["h_pt_jet1_3jet"]->fill(pT1);
             histos["h_pt_jet3_3jet"]->fill(pT3);
             histos["h_y_jet3_3jet"]->fill(rap3);
             histos["h_HT_3jet"]->fill(HT);
             histos["h_ST_3jet"]->fill(ST);
             if(njets == 3) {
               histos["h_ST_3jet_excl"]->fill(ST);
               histos["h_HT_3jet_excl"]->fill(HT);
             } else {
               const double pT4  = jets[3].pT() / GeV;
               const double rap4 = jets[3].absrap();
               histos["h_pt_jet4_4jet"]->fill(pT4);
               histos["h_y_jet4_4jet"]->fill(rap4);
               histos["h_HT_4jet"]->fill(HT);
               histos["h_ST_4jet"]->fill(ST);
               if (njets > 4) {
                 const double pT5  = jets[4].pT() / GeV;
                 const double rap5 = jets[4].absrap();
                 histos["h_pt_jet5_5jet"]->fill(pT5);
                 histos["h_y_jet5_5jet"]->fill(rap5);
                 histos["h_HT_5jet"]->fill(HT);
                 histos["h_ST_5jet"]->fill(ST);
               }
             }
           }
         }
       }
     }
 
 
     // Perform the per-event analysis
     void analyze(const Event& event) {
       // Retrieve boson candidate
       const WFinder& wfmu = apply<WFinder>(event, "WFmu");
       const WFinder& wfel = apply<WFinder>(event, "WFel");
 
       size_t nWmu = wfmu.size();
       size_t nWel = wfel.size();
 
       if (_mode == 0 && !((nWmu == 1 && !nWel) || (!nWmu && nWel == 1)))  vetoEvent; // one W->munu OR W->elnu candidate, otherwise veto
       if (_mode == 1 && !(!nWmu && nWel == 1))  vetoEvent; // one W->elnu candidate, otherwise veto
       if (_mode == 2 && !(nWmu == 1 && !nWel))  vetoEvent; // one W->munu candidate, otherwise veto
 
       // Retrieve jets
       const JetAlg& jetfs = apply<JetAlg>(event, "Jets");
       Jets all_jets = jetfs.jetsByPt(Cuts::pT > 30.0*GeV && Cuts::absrap < 4.4);
 
       const Particles& leptons = (nWmu? wfmu : wfel).constituentLeptons();
       const double missET = (nWmu? wfmu : wfel).constituentNeutrino().pT() / GeV;
       if (leptons.size() == 1 && missET > 25. && (nWmu? wfmu : wfel).mT() > 40*GeV) {
         const Particle& lep = leptons[0];
         fillPlots(lep, missET, all_jets);
       }
     }
 
 
     void finalize() {
       const double sf = _mode? 1.0 : 0.5;
       const double scalefactor = sf * crossSection() / sumOfWeights();
       for (const auto& hist : histos) {
         scale(hist.second, scalefactor);
       }
     }
 
 
   protected:
 
     size_t _mode;
 
 
   private:
 
     map<string, Histo1DPtr> histos;
 
   };
 
 
   DECLARE_RIVET_PLUGIN(ATLAS_2014_I1319490);
 
 }
diff --git a/analyses/pluginATLAS/ATLAS_2018_I1646686.cc b/analyses/pluginATLAS/ATLAS_2018_I1646686.cc
--- a/analyses/pluginATLAS/ATLAS_2018_I1646686.cc
+++ b/analyses/pluginATLAS/ATLAS_2018_I1646686.cc
@@ -1,309 +1,309 @@
 // -*- C++ -*-
 #include "Rivet/Analysis.hh"
 #include "Rivet/Projections/FinalState.hh"
 #include "Rivet/Projections/VetoedFinalState.hh"
 #include "Rivet/Projections/IdentifiedFinalState.hh"
 #include "Rivet/Projections/PromptFinalState.hh"
 #include "Rivet/Projections/DressedLeptons.hh"
 #include "Rivet/Projections/FastJets.hh"
 #include "Rivet/Projections/PartonicTops.hh"
 #include "Rivet/Math/LorentzTrans.hh"
 
 namespace Rivet {
 
 
   /// @brief All-hadronic ttbar at 13 TeV
   class ATLAS_2018_I1646686 : public Analysis {
   public:
 
       /// Constructor
       DEFAULT_RIVET_ANALYSIS_CTOR(ATLAS_2018_I1646686);
 
       /// Book histograms and initialise projections before the run
       void init() {
 
         // Get options particle-level only.
         _mode = 0;
         if ( getOption("TMODE") == "PARTICLE" ) _mode = 0;
         if ( getOption("TMODE") == "BOTH" ) _mode = 1;
 
         //histogram booking
         book(_h["inclusive"],1,1,1);
         bookHistograms("t_pt", 0, true);
         bookHistograms("t_y",  1, true);
         bookHistograms("t1_pt",         2);
         bookHistograms("t1_y",          3);
         bookHistograms("t2_pt",         4);
         bookHistograms("t2_y",          5);
         bookHistograms("tt_m",          6);
         bookHistograms("tt_pt",         7);
         bookHistograms("tt_y",          8);
         bookHistograms("tt_chi",        9);
         bookHistograms("tt_yboost",    10);
         bookHistograms("tt_pout",      11);
         bookHistograms("tt_dPhi",      12);
         bookHistograms("tt_Ht",        13);
         bookHistograms("tt_cosThStar", 14);
 
         // Projections
         Cut dressed_lep = (Cuts::abseta < 2.5) && (Cuts::pT >= 25*GeV);
         Cut eta_full = (Cuts::abseta < 5.0);
 
         // All final state particles
         FinalState fs(eta_full);
 
         // Get photons to dress leptons
         IdentifiedFinalState photons(fs);
         photons.acceptIdPair(PID::PHOTON);
 
         // Projection to find the electrons
         PromptFinalState electrons(Cuts::abspid == PID::ELECTRON, true);
         DressedLeptons dressedelectrons(photons, electrons, 0.1, dressed_lep);
         declare(dressedelectrons, "elecs");
         DressedLeptons ewdressedelectrons(photons, electrons, 0.1, eta_full);
 
         // Projection to find the muons
         PromptFinalState muons(Cuts::abspid == PID::MUON, true);
         DressedLeptons dressedmuons(photons, muons, 0.1, dressed_lep);
         declare(dressedmuons, "muons");
         DressedLeptons ewdressedmuons(photons, muons, 0.1, eta_full);
 
         // Jet clustering.
         VetoedFinalState vfs;
         vfs.addVetoOnThisFinalState(ewdressedelectrons);
         vfs.addVetoOnThisFinalState(ewdressedmuons);
 
-        FastJets jets(vfs, FastJets::ANTIKT, 0.4, JetAlg::DECAY_MUONS, JetAlg::DECAY_INVISIBLES);
+        FastJets jets(vfs, FastJets::ANTIKT, 0.4, JetAlg::Muons::DECAY, JetAlg::Invisibles::DECAY);
         declare(jets, "jets");
 
-        FastJets ljets(fs, FastJets::ANTIKT, 1.0, JetAlg::NO_MUONS, JetAlg::NO_INVISIBLES);
+        FastJets ljets(fs, FastJets::ANTIKT, 1.0, JetAlg::Muons::NONE, JetAlg::Invisibles::NONE);
         declare(ljets, "ljets" );
 
         if (_mode != 0 ){
           PartonicTops partonTops;
           declare(partonTops, "partonicTops");
         }
       }
 
 
       void analyze(const Event& event) {
 
 	if (_mode != 0){
 
           // Parton-level top quarks
           const Particles partonicTops = apply<PartonicTops>( event, "partonicTops").particlesByPt();
           FourMomentum top, tbar;
           bool foundT = false, foundTBar = false;
           for (const Particle& ptop : partonicTops) {
             const int pid = ptop.pid();
             if (pid == PID::TQUARK) {
               top = ptop.momentum();
               foundT = true;
             } else if (pid == -PID::TQUARK) {
               tbar = ptop.momentum();
               foundTBar = true;
             }
           }
 
 	  FourMomentum t1_parton, t2_parton, ttbar_parton;
 	  if ( foundT && foundTBar ) {
 	    t1_parton = top.pT2() > tbar.pT2() ? top : tbar;
 	    t2_parton = top.pT2() > tbar.pT2() ? tbar : top;
 	    ttbar_parton = t1_parton + t2_parton;
 	    
 	    if ( t1_parton.pT() > 500*GeV && t2_parton.pT() > 350*GeV) {
 	      
 	      const double chi_parton = calcChi(t1_parton, t2_parton);
 	      const double cosThetaStar_parton = abs(calcCosThetaStar(t1_parton, t2_parton));
 	      if (cosThetaStar_parton == -99) {
 		MSG_DEBUG("ttbar going faster than light! Vetoing event. Try turning of partonic tops?");
 		vetoEvent;
 	      }
 	      const double pout_parton = abs(calcPout(t1_parton, t2_parton));
 	      const double dPhi_parton = deltaPhi(t1_parton, t2_parton);
 	      
 	      const int randomChoice = rand() % 2;
 	      const FourMomentum& randomTopParton = (randomChoice == 0) ? t1_parton : t2_parton;
 	      
 	      fillParton("t_pt", randomTopParton.pT()/GeV);
 	      fillParton("t_y",  randomTopParton.absrap());
 	      
 	      fillParton("t1_pt", t1_parton.pT()/GeV);
 	      fillParton("t1_y",  t1_parton.absrap());
 	      fillParton("t2_pt", t2_parton.pT()/GeV);
 	      fillParton("t2_y",  t2_parton.absrap());
 	      
 	      fillParton("tt_m",  ttbar_parton.mass()/TeV);
 	      fillParton("tt_pt", ttbar_parton.pT()/GeV);
 	      fillParton("tt_Ht", (t1_parton.pT() + t2_parton.pT())/GeV);
 	      fillParton("tt_y",  ttbar_parton.absrap());
 
 	      fillParton("tt_yboost", 0.5 * abs(t1_parton.rapidity() + t2_parton.rapidity()));
 	      fillParton("tt_chi", chi_parton);
 	      fillParton("tt_cosThStar", cosThetaStar_parton);
 	      fillParton("tt_pout", pout_parton/GeV);
 	      fillParton("tt_dPhi", dPhi_parton);
 	    }
 	  }
         }
 
         // Get and veto on dressed leptons
         const vector<DressedLepton> dressedElectrons = apply<DressedLeptons>(event, "elecs").dressedLeptons();
         const vector<DressedLepton> dressedMuons     = apply<DressedLeptons>(event, "muons").dressedLeptons();
         if (!dressedElectrons.empty()) vetoEvent;
         if (!dressedMuons.empty()) vetoEvent;
 
         // Get jets
         const Jets& all_jets  = apply<FastJets>( event, "jets").jetsByPt(Cuts::pT > 25*GeV && Cuts::abseta < 2.5);
         const FastJets& ljets_fj = apply<FastJets>( event, "ljets");
         const Jets all_ljets = ljets_fj.jetsByPt();
 
         // Trim the large-R jets
         Jets trimmedJets;
         fastjet::Filter trimmer(fastjet::JetDefinition(fastjet::kt_algorithm, 0.2), fastjet::SelectorPtFractionMin(0.05));
         for (const Jet& jet : all_ljets)
           trimmedJets += ljets_fj.trimJet(jet, trimmer);
         trimmedJets = sortByPt(trimmedJets);
 
         // Check large-R jets
         Jets ljets;
         vector<bool> b_tagged;
         for (const Jet& jet : trimmedJets) {
 
           if (jet.pT() < 250 * GeV)  continue;
           if (jet.pT() > 3000 * GeV) continue;
           if (jet.mass() > jet.pT()) continue;
           if (jet.abseta() > 2.0 )   continue;
 
           ljets += jet;
           b_tagged += jet.bTagged();
         }
 
         if (all_jets.size() < 2)  vetoEvent;
         if (ljets.size() < 2)     vetoEvent;
 
         // Identify top and anti top, compute some event variables
         const FourMomentum ttbar = ljets[0].momentum() + ljets[1].momentum();
         const FourMomentum t1 = ljets[0].momentum();
         const FourMomentum t2 = ljets[1].momentum();
 
         const double chi = calcChi(t1, t2);
         const double cosThetaStar = abs(calcCosThetaStar(t1, t2));
 	if (cosThetaStar == -99) {
 	  MSG_DEBUG("real ttbar going faster than light! This should not happen. Vetoing event.");
 	  vetoEvent;
 	}
         const double pout = abs(calcPout(t1, t2));
         const double dPhi = deltaPhi(t1, t2);
 
         if ( t2.pT() < 350*GeV)  vetoEvent;
         if ( t1.pT() < 500*GeV)  vetoEvent;
 
         // b-tagging for particle done on large-R jets
         if (!(b_tagged[0] && b_tagged[1]))  vetoEvent;
 
         // Continues with signal region cuts
         if ( abs(t1.mass() - 172.5 * GeV) > 50*GeV )  vetoEvent;
         if ( abs(t2.mass() - 172.5 * GeV) > 50*GeV )  vetoEvent;
 
         _h["inclusive"]->fill(0);
 
         fillHistograms("t1_pt", t1.pT()/GeV);
         fillHistograms("t1_y",  t1.absrap());
         fillHistograms("t2_pt", t2.pT()/GeV);
         fillHistograms("t2_y",  t2.absrap());
 
         fillHistograms("tt_m",  ttbar.mass()/TeV);
         fillHistograms("tt_pt", ttbar.pT()/GeV);
         fillHistograms("tt_Ht", (t1.pT() + t2.pT())/GeV);
         fillHistograms("tt_y",  ttbar.absrap());
 
         fillHistograms("tt_yboost", 0.5 * abs(t1.rapidity() + t2.rapidity()));
         fillHistograms("tt_chi", chi);
         fillHistograms("tt_cosThStar", cosThetaStar);
         fillHistograms("tt_pout", pout/GeV);
         fillHistograms("tt_dPhi", dPhi);
 
       }
 
 
       void finalize() {
         // Normalize histograms
         const double sf = crossSection() / sumOfWeights();
         for (auto &hist : _h) {
           scale(hist.second, sf);
           if ((hist.first.find("_norm") != string::npos) && hist.second->integral(false)>0) hist.second->normalize(1.0, false);
         }
       }
 
 
       double calcChi(const FourMomentum& t1, const FourMomentum& t2) {
         double ystar = 0.5 * (t1.rapidity()-t2.rapidity());
         double chi = exp( 2 * abs(ystar));
         return chi;
       }
 
       double calcCosThetaStar(const FourMomentum& t1, const FourMomentum& t2) {
         FourMomentum ttbar = t1 + t2;
         LorentzTransform centreOfMassTrans;
         ttbar.setX(0);
         ttbar.setY(0);
 	if (ttbar.betaVec().mod2() > 1) return -99;
         centreOfMassTrans.setBetaVec( -ttbar.betaVec() );
         FourMomentum t1_star = centreOfMassTrans.transform(t1);
         double cosThetaStar;
         if (t1_star.p3().mod2() >= 0){
           cosThetaStar = t1_star.pz()/t1_star.p3().mod();
         } else {
           return -99;
         }
         return cosThetaStar;
       }
 
       double calcPout(const FourMomentum& t1, const FourMomentum& t2) {
         Vector3 t1V = t1.p3();
         Vector3 t2V = t2.p3();
         Vector3 zUnit = Vector3(0., 0., 1.);
         Vector3 vPerp = zUnit.cross(t1V);
 
         double pout = vPerp.dot(t2V)/vPerp.mod();
         return pout;
       }
 
 
     protected:
 
       size_t _mode;
 
     private:
 
       map<string, Histo1DPtr> _h;
 
       //some functions for booking, filling and scaling the histograms
       void fillHistograms(std::string name, double value) {
         _h[name]->fill(value);
         _h[name + "_norm"]->fill(value);
       }
 
       void fillParton(std::string name, double value) {
         _h[name + "_parton"]->fill(value);
         _h[name + "_parton_norm"]->fill(value);
       }
 
       void bookHistograms(const std::string name, unsigned int index, bool onlyParton = false) {
         if (!onlyParton) {
           book(_h[name], index, 1, 1 );
           book(_h[name + "_norm"], index + 13, 1, 1 );
         }
 	if (_mode != 0) {
 	  book(_h[name + "_parton"], index + 82, 1, 1 );
 	  book(_h[name + "_parton_norm"], index + 97, 1, 1 );
 	}
       }
 
   };
 
 
   DECLARE_RIVET_PLUGIN(ATLAS_2018_I1646686);
 
 }
diff --git a/analyses/pluginATLAS/ATLAS_2018_I1677498.cc b/analyses/pluginATLAS/ATLAS_2018_I1677498.cc
--- a/analyses/pluginATLAS/ATLAS_2018_I1677498.cc
+++ b/analyses/pluginATLAS/ATLAS_2018_I1677498.cc
@@ -1,109 +1,109 @@
 #include "Rivet/Analysis.hh"
 #include "Rivet/Projections/FinalState.hh"
 #include "Rivet/Projections/PromptFinalState.hh"
 #include "Rivet/Projections/DressedLeptons.hh"
 #include "Rivet/Projections/FastJets.hh"
 
 namespace Rivet {
 
 
   /// WWbb at 13 TeV
   class ATLAS_2018_I1677498 : public Analysis {
   public:
 
     /// Constructor
     DEFAULT_RIVET_ANALYSIS_CTOR(ATLAS_2018_I1677498);
 
 
     /// Book cuts and projections
     void init() {
 
       // All final state particles
       FinalState fs(Cuts::abseta < 5.0);
 
       PromptFinalState photons(Cuts::abspid == PID::PHOTON, true); // true accepts tau decays
 
       PromptFinalState bare_el(Cuts::abspid == PID::ELECTRON, true); // true accepts tau decays
       DressedLeptons elecs(photons, bare_el, 0.1, Cuts::pT > 7*GeV && Cuts::abseta < 2.47);
       declare(elecs, "elecs");
 
       PromptFinalState bare_mu(Cuts::abspid == PID::MUON, true); // accepts tau decays
       DressedLeptons muons(photons, bare_mu, 0.1, Cuts::pT > 6*GeV && Cuts::abseta < 2.5);
       declare(muons, "muons");
 
-      FastJets jets(fs, FastJets::ANTIKT, 0.4, JetAlg::NO_MUONS, JetAlg::NO_INVISIBLES);
+      FastJets jets(fs, FastJets::ANTIKT, 0.4, JetAlg::Muons::NONE, JetAlg::Invisibles::NONE);
       declare(jets, "jets");
 
-      _h = bookHisto1D(3, 1, 1);
+      book(_h, 3, 1, 1);
     }
 
 
     void analyze(const Event& event) {
 
       // Identify bjets (signal), light jets (OR) and soft b-jets (veto)
       size_t soft_bjets = 0;
       Jets bjets, lightjets;
       for (const Jet& jet : apply<FastJets>(event, "jets").jetsByPt(Cuts::pT > 5*GeV)) {
         bool isBjet = jet.bTagged(Cuts::pT > 5*GeV);
         if (isBjet) soft_bjets += 1;
         if (jet.abseta() < 2.5) {
           if ( isBjet && jet.pT() > 25*GeV) bjets += jet;
           if (!isBjet && jet.pT() > 20*GeV) lightjets += jet;
         }
       }
       if (soft_bjets != 2) vetoEvent;
       if (bjets.size() != 2) vetoEvent;
 
       // Get dressed leptons
       vector<DressedLepton> leptons;
       for (auto& lep : apply<DressedLeptons>(event, "muons").dressedLeptons()) { leptons.push_back(lep); }
       for (auto& lep : apply<DressedLeptons>(event, "elecs").dressedLeptons()) { leptons.push_back(lep); }
 
       // 1. Find which light jets survive OR
       for (const auto& lep : leptons) {
         ifilter_discard(lightjets, [&](const Jet& jet) {
           return deltaR(jet, lep) < 0.2 && (lep.abspid() == PID::ELECTRON || lep.pT()/jet.pT() > 0.7);
         });
       }
 
       // 2. Find which leptons survive the OR and apply signal selection
       for (const auto& jet : (lightjets + bjets)) {
         ifilter_discard(leptons, [&](const DressedLepton& lep) {
           return lep.pT() < 28*GeV || deltaR(jet, lep) < min(0.4, 0.04+10*GeV/lep.pT());
         });
       }
 
       if (leptons.size() != 2) vetoEvent;
       std::sort(leptons.begin(), leptons.end(), cmpMomByPt);
 
       // Z veto
       const size_t nEl = count(leptons, [](const DressedLepton& lep) { return  lep.abspid() == PID::ELECTRON; });
       const double mll = (leptons[0].mom() + leptons[1].mom()).mass();
       if (nEl != 1 && !(fabs(mll - 91*GeV) > 15*GeV && mll > 10*GeV)) vetoEvent;
 
       const double m00 = (leptons[0].mom() + bjets[0].mom()).mass();
       const double m10 = (leptons[1].mom() + bjets[0].mom()).mass();
       const double m01 = (leptons[0].mom() + bjets[1].mom()).mass();
       const double m11 = (leptons[1].mom() + bjets[1].mom()).mass();
       const double minimax = min( max(m00,m11), max(m10,m01) );
-      _h->fill(minimax/GeV, event.weight());
+      _h->fill(minimax/GeV);
     }
 
 
     /// Finalise
     void finalize() {
       normalize(_h);
     }
 
 
   private:
 
     /// Histogram
     Histo1DPtr _h;
 
   };
 
 
   DECLARE_RIVET_PLUGIN(ATLAS_2018_I1677498);
 
 }
diff --git a/analyses/pluginATLAS/ATLAS_2018_I1705857.cc b/analyses/pluginATLAS/ATLAS_2018_I1705857.cc
--- a/analyses/pluginATLAS/ATLAS_2018_I1705857.cc
+++ b/analyses/pluginATLAS/ATLAS_2018_I1705857.cc
@@ -1,246 +1,245 @@
 #include "Rivet/Analysis.hh"
 #include "Rivet/Projections/FastJets.hh"
 #include "Rivet/Projections/FinalState.hh"
 #include "Rivet/Projections/DressedLeptons.hh"
 #include "Rivet/Projections/PromptFinalState.hh"
 #include "Rivet/Projections/VetoedFinalState.hh"
 
 namespace Rivet {
 
 
 class ATLAS_2018_I1705857 : public Analysis {
  public:
    /// Constructor
    /// @brief ttbb at 13 TeV
    DEFAULT_RIVET_ANALYSIS_CTOR(ATLAS_2018_I1705857);
 
     void init() {
       // Eta ranges
       Cut eta_full = (Cuts::abseta < 5.0);
       // Lepton cuts
       Cut lep_cuts25 = (Cuts::abseta < 2.5) && (Cuts::pT >= 25*GeV);
       // All final state particles
       FinalState fs(eta_full);
 
       // Get photons to dress leptons
       PromptFinalState photons(eta_full && Cuts::abspid == PID::PHOTON, true);
 
       // Projection to find the electrons
       PromptFinalState electrons(eta_full && Cuts::abspid == PID::ELECTRON, true);
 
       // Projection to find the muons
       PromptFinalState muons(eta_full && Cuts::abspid == PID::MUON, true);
 
       DressedLeptons dressedelectrons25(photons, electrons, 0.1, lep_cuts25, true);
       DressedLeptons dressedmuons25(photons, muons, 0.1, lep_cuts25, true);
 
       declare(dressedelectrons25, "elecs");
       declare(dressedmuons25, "muons");
 
       // From here on we are just setting up the jet clustering
       IdentifiedFinalState nu_id;
       nu_id.acceptNeutrinos();
       PromptFinalState neutrinos(nu_id);
       neutrinos.acceptTauDecays(true);
 
       PromptFinalState jet_photons(eta_full && Cuts::abspid == PID::PHOTON, false);
       DressedLeptons all_dressed_electrons(jet_photons, electrons, 0.1, eta_full, true);
       DressedLeptons all_dressed_muons(jet_photons, muons, 0.1, eta_full, true);
 
       VetoedFinalState vfs(fs);
       vfs.addVetoOnThisFinalState(all_dressed_electrons);
       vfs.addVetoOnThisFinalState(all_dressed_muons);
       vfs.addVetoOnThisFinalState(neutrinos);
 
-      FastJets jets(vfs, FastJets::ANTIKT, 0.4, JetAlg::DECAY_MUONS, JetAlg::DECAY_INVISIBLES);
+      FastJets jets(vfs, FastJets::ANTIKT, 0.4, JetAlg::Muons::DECAY, JetAlg::Invisibles::DECAY);
       declare(jets, "jets");
 
       // fiducial cross-section histogram
-      _histograms["fid_xsec"] = bookHisto1D(1, 1, 1);
-      _histograms["fid_xsec_no_ttX"] = bookHisto1D(2, 1, 1);
+      book(_histograms["fid_xsec"], 1, 1, 1);
+      book(_histograms["fid_xsec_no_ttX"], 2, 1, 1);
 
-      _histograms["nbjets_emu"] = bookHisto1D(3, 1, 1);
-      _histograms["nbjets_emu_no_ttX"] = bookHisto1D(4, 1, 1);
+      book(_histograms["nbjets_emu"], 3, 1, 1);
+      book(_histograms["nbjets_emu_no_ttX"], 4, 1, 1);
 
       // HT
       book_hist("ht_emu", 3);
       book_hist("ht_had_emu", 4);
 
       book_hist("ht_ljets", 5);
       book_hist("ht_had_ljets", 6);
 
       // b-jet pTs
       book_hist("lead_bjet_pt_emu",    7);
       book_hist("sublead_bjet_pt_emu", 8);
       book_hist("third_bjet_pt_emu",   9);
 
       book_hist("lead_bjet_pt_ljets",    10);
       book_hist("sublead_bjet_pt_ljets", 11);
       book_hist("third_bjet_pt_ljets",   12);
       book_hist("fourth_bjet_pt_ljets",  13);
 
       // leading bb pair
       book_hist("m_bb_leading_emu",  14);
       book_hist("pt_bb_leading_emu", 15);
       book_hist("dR_bb_leading_emu", 16);
 
       book_hist("m_bb_leading_ljets",  17);
       book_hist("pt_bb_leading_ljets", 18);
       book_hist("dR_bb_leading_ljets", 19);
 
       // closest bb pair
       book_hist("m_bb_closest_emu",  20);
       book_hist("pt_bb_closest_emu", 21);
       book_hist("dR_bb_closest_emu", 22);
 
       book_hist("m_bb_closest_ljets",  23);
       book_hist("pt_bb_closest_ljets", 24);
       book_hist("dR_bb_closest_ljets", 25);
     }
 
 
     void analyze(const Event& event) {
-      const double weight = event.weight();
 
       vector<DressedLepton> leptons;
       for (auto &lep : apply<DressedLeptons>(event, "muons").dressedLeptons()) { leptons.push_back(lep); }
       for (auto &lep : apply<DressedLeptons>(event, "elecs").dressedLeptons()) { leptons.push_back(lep); }
 
       const Jets jets = apply<FastJets>(event, "jets").jetsByPt(Cuts::pT > 25*GeV && Cuts::abseta < 2.5);
       for (const auto& jet : jets) {
         ifilter_discard(leptons, [&](const DressedLepton& lep) { return deltaR(jet, lep) < 0.4; });
       }
 
       Jets bjets;
       for (const Jet& jet : jets) {
         if (jet.bTagged(Cuts::pT >= 5*GeV))  bjets += jet;
       }
 
       size_t njets = jets.size();
       size_t nbjets = bjets.size();
 
       // Evaluate basic event selection
       bool pass_ljets = (leptons.size() == 1 && leptons[0].pT() > 27*GeV);
 
       bool pass_emu =
         // 2 leptons > 27 GeV
         (leptons.size() == 2) &&
         (leptons[0].pT() > 27*GeV && leptons[1].pT() > 27*GeV) &&
         // emu events
         ((leptons[0].abspid() == 11 && leptons[1].abspid() == 13) ||
          (leptons[0].abspid() == 13 && leptons[1].abspid() == 11)) &&
         // opposite charge
         (leptons[0].charge() != leptons[1].charge());
 
       // If we don't have exactly 1 or 2 leptons then veto the event
       if (!pass_emu && !pass_ljets)  vetoEvent;
 
       if (pass_emu) {
-        if (nbjets >= 2)  fill("nbjets_emu", nbjets - 1, weight);
-        if (nbjets >= 3)  fill("fid_xsec", 1, weight);
-        if (nbjets >= 4)  fill("fid_xsec", 2, weight);
+        if (nbjets >= 2)  fill("nbjets_emu", nbjets - 1);
+        if (nbjets >= 3)  fill("fid_xsec", 1);
+        if (nbjets >= 4)  fill("fid_xsec", 2);
       }
 
       if (pass_ljets) {
-        if (nbjets >= 3 && njets >= 5)  fill("fid_xsec", 3, weight);
-        if (nbjets >= 4 && njets >= 6)  fill("fid_xsec", 4, weight);
+        if (nbjets >= 3 && njets >= 5)  fill("fid_xsec", 3);
+        if (nbjets >= 4 && njets >= 6)  fill("fid_xsec", 4);
       }
 
       if (pass_emu && (nbjets < 3 || njets < 3))    vetoEvent;
       if (pass_ljets && (nbjets < 4 || njets < 6))  vetoEvent;
 
       double hthad = sum(jets, pT, 0.0);
       double ht = sum(leptons, pT, hthad);
 
       FourMomentum jsum = bjets[0].momentum() + bjets[1].momentum();
       double dr_leading = deltaR(bjets[0], bjets[1]);
 
       size_t ind1, ind2; double mindr = 999.;
       for (size_t i = 0; i < bjets.size(); ++i) {
         for (size_t j = 0; j < bjets.size(); ++j) {
           if (i == j)  continue;
           double dr = deltaR(bjets[i], bjets[j]);
           if (dr < mindr) {
             ind1 = i;
             ind2 = j;
             mindr = dr;
           }
         }
       }
 
       FourMomentum bb_closest = bjets[ind1].momentum() + bjets[ind2].momentum();
       double dr_closest = deltaR(bjets[ind1], bjets[ind2]);
 
       if (pass_ljets) {
         // b-jet pTs
-        fill("lead_bjet_pt_ljets", bjets[0].pT()/GeV, weight);
-        fill("sublead_bjet_pt_ljets", bjets[1].pT()/GeV, weight);
-        fill("third_bjet_pt_ljets", bjets[2].pT()/GeV, weight);
+        fill("lead_bjet_pt_ljets", bjets[0].pT()/GeV);
+        fill("sublead_bjet_pt_ljets", bjets[1].pT()/GeV);
+        fill("third_bjet_pt_ljets", bjets[2].pT()/GeV);
 
-        if (nbjets >= 4)  fill("fourth_bjet_pt_ljets", bjets[3].pT()/GeV, weight);
+        if (nbjets >= 4)  fill("fourth_bjet_pt_ljets", bjets[3].pT()/GeV);
 
         // HT
-        fill("ht_ljets", ht/GeV, weight);
-        fill("ht_had_ljets", hthad/GeV, weight);
+        fill("ht_ljets", ht/GeV);
+        fill("ht_had_ljets", hthad/GeV);
 
         // leading bb pair
-        fill("m_bb_leading_ljets", jsum.mass()/GeV, weight);
-        fill("pt_bb_leading_ljets", jsum.pT()/GeV, weight);
-        fill("dR_bb_leading_ljets", dr_leading, weight);
+        fill("m_bb_leading_ljets", jsum.mass()/GeV);
+        fill("pt_bb_leading_ljets", jsum.pT()/GeV);
+        fill("dR_bb_leading_ljets", dr_leading);
 
         // closest bb pair
-        fill("m_bb_closest_ljets", bb_closest.mass()/GeV, weight);
-        fill("pt_bb_closest_ljets", bb_closest.pT()/GeV, weight);
-        fill("dR_bb_closest_ljets", dr_closest, weight);
+        fill("m_bb_closest_ljets", bb_closest.mass()/GeV);
+        fill("pt_bb_closest_ljets", bb_closest.pT()/GeV);
+        fill("dR_bb_closest_ljets", dr_closest);
       }
       if (pass_emu) {
         // b-jet pTs
-        fill("lead_bjet_pt_emu", bjets[0].pT()/GeV, weight);
-        fill("sublead_bjet_pt_emu", bjets[1].pT()/GeV, weight);
-        fill("third_bjet_pt_emu", bjets[2].pT()/GeV, weight);
+        fill("lead_bjet_pt_emu", bjets[0].pT()/GeV);
+        fill("sublead_bjet_pt_emu", bjets[1].pT()/GeV);
+        fill("third_bjet_pt_emu", bjets[2].pT()/GeV);
 
         // HT
-        fill("ht_emu", ht/GeV, weight);
-        fill("ht_had_emu", hthad/GeV, weight);
+        fill("ht_emu", ht/GeV);
+        fill("ht_had_emu", hthad/GeV);
 
         // leading bb pair
-        fill("m_bb_leading_emu", jsum.mass()/GeV, weight);
-        fill("pt_bb_leading_emu", jsum.pT()/GeV, weight);
-        fill("dR_bb_leading_emu", dr_leading, weight);
+        fill("m_bb_leading_emu", jsum.mass()/GeV);
+        fill("pt_bb_leading_emu", jsum.pT()/GeV);
+        fill("dR_bb_leading_emu", dr_leading);
 
         // closest bb pair
-        fill("m_bb_closest_emu", bb_closest.mass()/GeV, weight);
-        fill("pt_bb_closest_emu", bb_closest.pT()/GeV, weight);
-        fill("dR_bb_closest_emu", dr_closest, weight);
+        fill("m_bb_closest_emu", bb_closest.mass()/GeV);
+        fill("pt_bb_closest_emu", bb_closest.pT()/GeV);
+        fill("dR_bb_closest_emu", dr_closest);
       }
     }
 
     void finalize() {
       // Normalise all histograms
       const double sf = crossSection() / femtobarn / sumOfWeights();
       for (auto const& h : _histograms) {
         scale(h.second, sf);
         if (h.first.find("fid_xsec") != string::npos)  continue;
         normalize(h.second, 1.0);
       }
     }
 
-    void fill(const string& name, const double value, const double weight) {
-      _histograms[name]->fill(value, weight);
-      _histograms[name + "_no_ttX"]->fill(value, weight);
+    void fill(const string& name, const double value) {
+      _histograms[name]->fill(value);
+      _histograms[name + "_no_ttX"]->fill(value);
     }
 
     void book_hist(const std::string& name, unsigned int d) {
       // ttX substracted histograms are even numbers
-      _histograms[name] = bookHisto1D((d * 2) - 1, 1, 1);
-      _histograms[name + "_no_ttX"] = bookHisto1D(d * 2, 1, 1);
+      book(_histograms[name], (d * 2) - 1, 1, 1);
+      book(_histograms[name + "_no_ttX"], d * 2, 1, 1);
     }
 
     private:
       map<std::string, Histo1DPtr> _histograms;
 
   };
 
   // The hook for the plugin system
   DECLARE_RIVET_PLUGIN(ATLAS_2018_I1705857);
 }
diff --git a/analyses/pluginATLAS/ATLAS_2018_I1711114.cc b/analyses/pluginATLAS/ATLAS_2018_I1711114.cc
--- a/analyses/pluginATLAS/ATLAS_2018_I1711114.cc
+++ b/analyses/pluginATLAS/ATLAS_2018_I1711114.cc
@@ -1,117 +1,115 @@
 #include "Rivet/Analysis.hh"
 #include "Rivet/Projections/FinalState.hh"
 #include "Rivet/Projections/ChargedFinalState.hh"
 #include "Rivet/Projections/FastJets.hh"
 
 namespace Rivet {
 
 
   /// g -> bb at 13 TeV
   class ATLAS_2018_I1711114: public Analysis {
   public:
 
     /// Constructor
     DEFAULT_RIVET_ANALYSIS_CTOR(ATLAS_2018_I1711114);
 
 
     /// Book cuts and projections
     void init() {
       // All final state particles
       FinalState fs(Cuts::abseta<5.0);
 
       ChargedFinalState cfs(Cuts::pT > 0.5*GeV && Cuts::abseta < 2.5);
-      FastJets smallR_jets(cfs, FastJets::ANTIKT, 0.2, JetAlg::NO_MUONS, JetAlg::NO_INVISIBLES);
+      FastJets smallR_jets(cfs, FastJets::ANTIKT, 0.2, JetAlg::Muons::NONE, JetAlg::Invisibles::NONE);
       declare(smallR_jets, "track_jets");
 
-      FastJets largeR_jets(fs, FastJets::ANTIKT, 1.0, JetAlg::NO_MUONS, JetAlg::NO_INVISIBLES);
+      FastJets largeR_jets(fs, FastJets::ANTIKT, 1.0, JetAlg::Muons::NONE, JetAlg::Invisibles::NONE);
       declare(largeR_jets, "largeR_jets");
 
-      _h_R   = bookHisto1D(1,1,1);
-      _h_phi = bookHisto1D(2,1,1);
-      _h_z   = bookHisto1D(3,1,1);
-      _h_rho = bookHisto1D(4,1,1);
+      book(_h_R, 1,1,1);
+      book(_h_phi, 2,1,1);
+      book(_h_z, 3,1,1);
+      book(_h_rho, 4,1,1);
     }
 
 
     void analyze(const Event& event) {
 
-      const double weight = event.weight();
-
       const PseudoJets& myJets = apply<FastJets>(event, "largeR_jets").pseudoJetsByPt(450*GeV);
       if (myJets.empty()) vetoEvent;
 
       fastjet::Filter trimmer(fastjet::JetDefinition(fastjet::kt_algorithm, 0.2), fastjet::SelectorPtFractionMin(0.05));
       Jets myTrimmedJets;
       for (const Jet& jet : myJets)  myTrimmedJets += Jet(trimmer(jet));
       std::sort(myTrimmedJets.begin(), myTrimmedJets.end(), cmpMomByPt);
       if (myTrimmedJets[0].pT() < 450*GeV) vetoEvent;
 
       const Jets& myJets_charged = apply<FastJets>(event, "track_jets").jetsByPt(Cuts::pT > 10*GeV);
       PseudoJets pjs;
       for (auto tj : myTrimmedJets[0].pseudojet().constituents()) {
         fastjet::PseudoJet pj = tj;
         pj.set_user_index(-1); // dummmy
         pjs.push_back(pj);
       }
       for (size_t i = 0; i < myJets_charged.size(); ++i) {
         fastjet::PseudoJet pj = myJets_charged[i];
         pj *= 1e-20; // ghostify momentum
         pj.set_user_index(i);
         pjs.push_back(pj);
       }
       fastjet::ClusterSequence tagged_seq(pjs, fastjet::JetDefinition(fastjet::antikt_algorithm, 1.0));
       PseudoJets GAfatjet = fastjet::sorted_by_pt(tagged_seq.inclusive_jets(50.0));
       Jets associated_trackjets;
       for (auto pj : GAfatjet[0].constituents()) {
         if (pj.user_index() >= 0)  associated_trackjets += myJets_charged[pj.user_index()];
       }
       if (associated_trackjets.size() < 2) vetoEvent;
       std::sort(associated_trackjets.begin(), associated_trackjets.end(), cmpMomByPt);
 
       size_t nbtags = 0;
       for (unsigned int ij = 0; ij < 2; ++ij) {
         if (associated_trackjets[ij].bTagged(Cuts::pT > 5*GeV))  ++nbtags;
       }
       if (nbtags != 2) vetoEvent;
 
       // Now, time to compute the observables!
       const Vector3 b1v = associated_trackjets[0].p3();
       const Vector3 b2v = associated_trackjets[1].p3();
       const Vector3 plane1 = b1v.cross(b2v);
       const Vector3 gv = b1v + b2v;
       const Vector3 beam = Vector3(0,0,1);
       const Vector3 plane2 = beam.cross(gv);
 
       const double fTz = associated_trackjets[1].pT() / (associated_trackjets[0].pT()+associated_trackjets[1].pT());
       const double fTR = deltaR(associated_trackjets[0], associated_trackjets[1], RapScheme::YRAP); //N.B. this uses y and not eta
       const FourMomentum dijet = associated_trackjets[0].mom() + associated_trackjets[1].mom();
       const double fTrho = log(dijet.mass() / dijet.pT());
       const double fTphi = (plane1).angle(plane2)/M_PI;
 
-      _h_R->fill(  fTR,   weight);
-      _h_phi->fill(fTphi, weight);
-      _h_z->fill(  fTz,   weight);
-      _h_rho->fill(fTrho, weight);
+      _h_R->fill(  fTR);
+      _h_phi->fill(fTphi);
+      _h_z->fill(  fTz);
+      _h_rho->fill(fTrho);
     }
 
 
     /// Scale histos
     void finalize() {
       _h_R->normalize(  1.0, false);
       _h_phi->normalize(1.0, false);
       _h_z->normalize(  1.0, false);
       _h_rho->normalize(1.0, false);
     }
 
 
   private:
 
     /// Histograms
     Histo1DPtr _h_z, _h_R, _h_rho, _h_phi;
 
   };
 
 
   DECLARE_RIVET_PLUGIN(ATLAS_2018_I1711114);
 
 }
diff --git a/analyses/pluginATLAS/ATLAS_2019_I1720442.cc b/analyses/pluginATLAS/ATLAS_2019_I1720442.cc
--- a/analyses/pluginATLAS/ATLAS_2019_I1720442.cc
+++ b/analyses/pluginATLAS/ATLAS_2019_I1720442.cc
@@ -1,242 +1,240 @@
 // -*- C++ -*-
 #include "Rivet/Analysis.hh"
 #include "Rivet/Projections/FinalState.hh"
 #include "Rivet/Projections/PromptFinalState.hh"
 #include "Rivet/Projections/DressedLeptons.hh"
 
 namespace Rivet {
 
 
   /// ATLAS 4-lepton lineshape at 13 TeV
   class ATLAS_2019_I1720442 : public Analysis {
   public:
 
     /// Constructor
     DEFAULT_RIVET_ANALYSIS_CTOR(ATLAS_2019_I1720442);
 
     void init() {
 
       PromptFinalState photons(Cuts::abspid == PID::PHOTON);
       PromptFinalState elecs(Cuts::abspid == PID::ELECTRON);
       PromptFinalState muons(Cuts::abspid == PID::MUON);
 
       // Selection
       Cut el_fid_sel = (Cuts::abseta < 2.47) && (Cuts::pT > 7*GeV);
       Cut mu_fid_sel = (Cuts::abseta < 2.7) && (Cuts::pT > 5*GeV);
 
       DressedLeptons dressed_elecs(photons, elecs, 0.005, el_fid_sel, false);
       declare(dressed_elecs, "elecs");
 
       DressedLeptons dressed_muons(photons, muons, 0.005, mu_fid_sel, false);
       declare(dressed_muons, "muons");
 
       // Book histos
-      _h["m4l_inclusive"] = bookHisto1D(1,1,1);
+      book(_h["m4l_inclusive"], 1,1,1);
 
-      _h["m4l_ptslice1"] = bookHisto1D(2,1,1);
-      _h["m4l_ptslice2"] = bookHisto1D(3,1,1);
-      _h["m4l_ptslice3"] = bookHisto1D(4,1,1);
-      _h["m4l_ptslice4"] = bookHisto1D(5,1,1);
+      book(_h["m4l_ptslice1"], 2,1,1);
+      book(_h["m4l_ptslice2"], 3,1,1);
+      book(_h["m4l_ptslice3"], 4,1,1);
+      book(_h["m4l_ptslice4"], 5,1,1);
 
-      _h["m4l_rapidityslice1"] = bookHisto1D(6,1,1);
-      _h["m4l_rapidityslice2"] = bookHisto1D(7,1,1);
-      _h["m4l_rapidityslice3"] = bookHisto1D(8,1,1);
-      _h["m4l_rapidityslice4"] = bookHisto1D(9,1,1);
+      book(_h["m4l_rapidityslice1"], 6,1,1);
+      book(_h["m4l_rapidityslice2"], 7,1,1);
+      book(_h["m4l_rapidityslice3"], 8,1,1);
+      book(_h["m4l_rapidityslice4"], 9,1,1);
 
-      _h["m4l_4mu"]   = bookHisto1D(12,1,1);
-      _h["m4l_4e"]    = bookHisto1D(13,1,1);
-      _h["m4l_2e2mu"] = bookHisto1D(14,1,1);
+      book(_h["m4l_4mu"], 12,1,1);
+      book(_h["m4l_4e"], 13,1,1);
+      book(_h["m4l_2e2mu"], 14,1,1);
     }
 
 
     /// @brief Generic dilepton candidate
     /// @todo Move into the Rivet core?
     struct Dilepton : public ParticlePair {
       Dilepton() { }
       Dilepton(ParticlePair _particlepair) : ParticlePair(_particlepair) {
         assert(first.abspid() == second.abspid());
       }
       FourMomentum mom() const { return first.momentum() + second.momentum(); }
       operator FourMomentum() const { return mom(); }
       static bool cmppT(const Dilepton& lx, const Dilepton& rx) { return lx.mom().pT() < rx.mom().pT(); }
       int flavour() const { return first.abspid(); }
       double pTl1() const { return first.pT(); }
       double pTl2() const { return second.pT(); }
     };
 
 
     struct Quadruplet {
       Quadruplet (Dilepton z1, Dilepton z2): _z1(z1), _z2(z2) { }
       enum class FlavCombi { mm=0, ee, me, em, undefined };
       FourMomentum mom() const { return _z1.mom() + _z2.mom(); }
       Dilepton getZ1() const { return _z1; }
       Dilepton getZ2() const { return _z2; }
       Dilepton _z1, _z2;
       FlavCombi type() const {
         if (     _z1.flavour() == 13 && _z2.flavour() == 13) { return FlavCombi::mm; }
         else if (_z1.flavour() == 11 && _z2.flavour() == 11) { return FlavCombi::ee; }
         else if (_z1.flavour() == 13 && _z2.flavour() == 11) { return FlavCombi::me; }
         else if (_z1.flavour() == 11 && _z2.flavour() == 13) { return FlavCombi::em; }
         else  return FlavCombi::undefined;
       }
     };
 
 
     vector<Quadruplet> getBestQuads(Particles& particles) {
       // H->ZZ->4l pairing
       // - Two same flavor opposite charged leptons
       // - Ambiguities in pairing are resolved by choosing the combination
       //     that results in the smaller value of |mll - mZ| for each pair successively
       vector<Quadruplet> quads {};
 
       size_t n_parts = particles.size();
       if (n_parts < 4)  return quads;
 
       // STEP 1: find SFOS pairs
       vector<Dilepton> SFOS;
       for (size_t i = 0; i < n_parts; ++i) {
         for (size_t j = 0; j < i; ++j) {
           if (particles[i].pid() == -particles[j].pid()) {
             // sort such that the negative lepton is listed first
             if (particles[i].pid() > 0)  SFOS.push_back(Dilepton(make_pair(particles[i], particles[j])));
             else                         SFOS.push_back(Dilepton(make_pair(particles[j], particles[i])));
           }
         }
       }
       if (SFOS.size() < 2)  return quads;
 
       // now we sort the SFOS pairs
       std::sort(SFOS.begin(), SFOS.end(), [](const Dilepton& p1, const Dilepton& p2) {
           return fabs(p1.mom().mass() - Z_mass) < fabs(p2.mom().mass() - Z_mass);
         });
 
       // Form all possible quadruplets passing the pT cuts
       for (size_t k = 0; k < SFOS.size(); ++k) {
         for (size_t l = k+1; l < SFOS.size(); ++l) {
           if (deltaR(SFOS[k].first.mom(),  SFOS[l].first.mom())  < 1e-13)  continue;
           if (deltaR(SFOS[k].first.mom(),  SFOS[l].second.mom()) < 1e-13)  continue;
           if (deltaR(SFOS[k].second.mom(), SFOS[l].first.mom())  < 1e-13)  continue;
           if (deltaR(SFOS[k].second.mom(), SFOS[l].second.mom()) < 1e-13)  continue;
 
           vector<double> lep_pt { SFOS[k].pTl1(), SFOS[k].pTl2(), SFOS[l].pTl1(), SFOS[l].pTl2() };
           std::sort(lep_pt.begin(), lep_pt.end(), std::greater<double>());
           if (!(lep_pt[0] > 20*GeV && lep_pt[1] > 15*GeV && lep_pt[2] > 10*GeV)) continue;
           quads.push_back( Quadruplet(SFOS[k], SFOS[l]) );
         }
       }
       return quads;
     }
 
 
     bool passMassCuts(const Quadruplet& theQuad){
       const vector<double> cuts_m34{ 5*GeV, 5*GeV, 12*GeV, 12*GeV, 50*GeV };
       const vector<double> cuts_m4l{ 0, 100*GeV, 110*GeV, 140*GeV, 190*GeV };
 
       double m4l = theQuad.mom().mass();
       double mZ1 = theQuad.getZ1().mom().mass();
       double mZ2 = theQuad.getZ2().mom().mass();
 
       // Invariant-mass requirements
       double cutval = cuts_m34.back();
       for (size_t k = 0; k < cuts_m34.size(); ++k) {
         if (cuts_m4l[k] > m4l) {
           cutval = cuts_m34[k-1] + (cuts_m34[k] - cuts_m34[k-1])/(cuts_m4l[k] - cuts_m4l[k-1]) * (m4l - cuts_m4l[k-1]);
           break;
         }
       }
       return inRange(mZ1, 50*GeV, 106*GeV) && inRange(mZ2, cutval, 115*GeV);
     }
 
 
     bool pass_dRll(const Quadruplet& theQuad) {
       const double dR_min_same = 0.1;
       const double dR_min_opp = 0.2;
       double dr_min_cross = dR_min_opp;
       if (theQuad.getZ1().flavour() == theQuad.getZ2().flavour()) {
         dr_min_cross = dR_min_same;
       }
       return !((deltaR(theQuad.getZ1().first,  theQuad.getZ1().second) < dR_min_same)  ||
                (deltaR(theQuad.getZ2().first,  theQuad.getZ2().second) < dR_min_same)  ||
                (deltaR(theQuad.getZ1().first,  theQuad.getZ2().first)  < dr_min_cross) ||
                (deltaR(theQuad.getZ1().first,  theQuad.getZ2().second) < dr_min_cross) ||
                (deltaR(theQuad.getZ1().second, theQuad.getZ2().first)  < dr_min_cross) ||
                (deltaR(theQuad.getZ1().second, theQuad.getZ2().second) < dr_min_cross));
     }
 
 
     bool pass_Jpsi(const Quadruplet& theQuad){
       Particles all_leps { theQuad.getZ1().first, theQuad.getZ1().second, theQuad.getZ2().first, theQuad.getZ2().second };
       for (const Particle& lep1 : all_leps) {
         for (const Particle& lep2 : all_leps) {
           if (lep1.pid() == -lep2.pid() && (lep1.mom() + lep2.mom()).mass() < 5*GeV) return false;
         }
       }
       return true;
     }
 
 
     // Handle 3 further CF stages - m12/34, dRmin, jpsi veto
     bool passSelection (const Quadruplet& theQuad){
       return passMassCuts(theQuad) && pass_dRll(theQuad) && pass_Jpsi(theQuad);
     }
 
 
     // Do the analysis
     void analyze(const Event& event) {
 
-      const double weight = event.weight();
-
       //preselection of leptons for ZZ-> llll final state
       Particles dressed_leptons;
       for (auto lep : apply<DressedLeptons>(event, "muons").dressedLeptons()) { dressed_leptons.push_back(lep); }
       for (auto lep : apply<DressedLeptons>(event, "elecs").dressedLeptons()) { dressed_leptons.push_back(lep); }
 
       auto foundDressed = getBestQuads(dressed_leptons);
       // if we don't find any quad, we can stop here
       if (foundDressed.empty())  vetoEvent;
 
       bool pass = passSelection(foundDressed[0]);
       if (pass) {
         double m4l = foundDressed[0].mom().mass()/GeV;
         double pt4l = foundDressed[0].mom().pT()/GeV;
         double y4l = foundDressed[0].mom().absrap();
         Quadruplet::FlavCombi flavour = foundDressed[0].type();
-        _h["m4l_inclusive"]->fill(m4l, weight);
-        if (     pt4l <  20.)  _h["m4l_ptslice1"]->fill(m4l,weight);
-        else if (pt4l <  50.)  _h["m4l_ptslice2"]->fill(m4l,weight);
-        else if (pt4l < 100.)  _h["m4l_ptslice3"]->fill(m4l,weight);
-        else if (pt4l < 600.)  _h["m4l_ptslice4"]->fill(m4l,weight);
+        _h["m4l_inclusive"]->fill(m4l);
+        if (     pt4l <  20.)  _h["m4l_ptslice1"]->fill(m4l);
+        else if (pt4l <  50.)  _h["m4l_ptslice2"]->fill(m4l);
+        else if (pt4l < 100.)  _h["m4l_ptslice3"]->fill(m4l);
+        else if (pt4l < 600.)  _h["m4l_ptslice4"]->fill(m4l);
 
-        if (     y4l < 0.4)  _h["m4l_rapidityslice1"]->fill(m4l,weight);
-        else if (y4l < 0.8)  _h["m4l_rapidityslice2"]->fill(m4l,weight);
-        else if (y4l < 1.2)  _h["m4l_rapidityslice3"]->fill(m4l,weight);
-        else if (y4l < 2.5)  _h["m4l_rapidityslice4"]->fill(m4l,weight);
+        if (     y4l < 0.4)  _h["m4l_rapidityslice1"]->fill(m4l);
+        else if (y4l < 0.8)  _h["m4l_rapidityslice2"]->fill(m4l);
+        else if (y4l < 1.2)  _h["m4l_rapidityslice3"]->fill(m4l);
+        else if (y4l < 2.5)  _h["m4l_rapidityslice4"]->fill(m4l);
 
-        if (     flavour == Quadruplet::FlavCombi::mm) _h["m4l_4mu"]->fill(m4l,weight);
-        else if (flavour == Quadruplet::FlavCombi::ee) _h["m4l_4e"]->fill(m4l,weight);
+        if (     flavour == Quadruplet::FlavCombi::mm) _h["m4l_4mu"]->fill(m4l);
+        else if (flavour == Quadruplet::FlavCombi::ee) _h["m4l_4e"]->fill(m4l);
         else if (flavour == Quadruplet::FlavCombi::me || flavour == Quadruplet::FlavCombi::em) {
-          _h["m4l_2e2mu"]->fill(m4l,weight);
+          _h["m4l_2e2mu"]->fill(m4l);
         }
       }
 
     }
 
 
     /// Finalize
     void finalize() {
       const double sf = crossSection() / femtobarn / sumOfWeights();
       for (auto hist : _h) { scale(hist.second, sf); }
     }
 
 
   private:
 
     map<string, Histo1DPtr> _h;
     static constexpr double Z_mass = 91.1876;
 
   };
 
 
   DECLARE_RIVET_PLUGIN(ATLAS_2019_I1720442);
 
 }
diff --git a/analyses/pluginBABAR/BABAR_2001_I558091.cc b/analyses/pluginBABAR/BABAR_2001_I558091.cc
--- a/analyses/pluginBABAR/BABAR_2001_I558091.cc
+++ b/analyses/pluginBABAR/BABAR_2001_I558091.cc
@@ -1,84 +1,85 @@
 // -*- C++ -*-
 #include "Rivet/Analysis.hh"
 #include "Rivet/Projections/UnstableParticles.hh"
 
 namespace Rivet {
 
 
   /// @brief Add a short analysis description here
   class BABAR_2001_I558091 : public Analysis {
   public:
 
     /// Constructor
     DEFAULT_RIVET_ANALYSIS_CTOR(BABAR_2001_I558091);
 
 
     /// @name Analysis methods
     //@{
 
     /// Book histograms and initialise projections before the run
     void init() {
       declare(UnstableParticles(), "UFS");
-      _c_jpsi = bookCounter("/TMP/jpsi");
+      book(_c_jpsi, "/TMP/jpsi");
     }
 
 
     /// Perform the per-event analysis
     void analyze(const Event& event) {
       const UnstableParticles& ufs = apply<UnstableParticles>(event, "UFS");
       double nJsi=0.;
-      foreach (const Particle& p, ufs.particles()) {
-        if (p.pdgId()==443) {
+      for (const Particle& p : ufs.particles()) {
+        if (p.pid()==443) {
 	  bool fs = true;
-	  foreach (const Particle & child, p.children()) {
-	    if(child.pdgId()==443) {
+	  for (const Particle & child : p.children()) {
+	    if(child.pid()==443) {
 	      fs = false;
 	      break;
 	    }
 	  }
 	  if(fs) nJsi += 1.;
 	}
       }
-      _c_jpsi->fill(nJsi*event.weight());
+      _c_jpsi->fill(nJsi);
     }
 
 
     /// Normalise histograms etc., after the run
     void finalize() {
       double fact = crossSection()/ sumOfWeights() /picobarn;
       double sigma = _c_jpsi->val()*fact;
       double error = _c_jpsi->err()*fact;
       Scatter2D temphisto(refData(1, 1, 1));
-      Scatter2DPtr mult = bookScatter2D(1, 1, 1);
+      Scatter2DPtr mult;
+      book(mult, 1, 1, 1);
       for (size_t b = 0; b < temphisto.numPoints(); b++) {
 	const double x  = temphisto.point(b).x();
 	pair<double,double> ex = temphisto.point(b).xErrs();
 	pair<double,double> ex2 = ex;
 	if(ex2.first ==0.) ex2. first=0.0001;
 	if(ex2.second==0.) ex2.second=0.0001;
 	if (inRange(sqrtS()/GeV, x-ex2.first, x+ex2.second)) {
 	  mult->addPoint(x, sigma, ex, make_pair(error,error));
 	}
 	else {
 	  mult->addPoint(x, 0., ex, make_pair(0.,.0));
 	}
       }
     }
 
     //@}
 
 
     /// @name Histograms
     //@{
     CounterPtr _c_jpsi;
     //@}
 
 
   };
 
 
   // The hook for the plugin system
   DECLARE_RIVET_PLUGIN(BABAR_2001_I558091);
 
 
 }
diff --git a/analyses/pluginBABAR/BABAR_2004_I656680.cc b/analyses/pluginBABAR/BABAR_2004_I656680.cc
--- a/analyses/pluginBABAR/BABAR_2004_I656680.cc
+++ b/analyses/pluginBABAR/BABAR_2004_I656680.cc
@@ -1,88 +1,89 @@
 // -*- C++ -*-
 #include "Rivet/Analysis.hh"
 #include "Rivet/Projections/FinalState.hh"
 
 
 namespace Rivet {
 
 
   /// @brief Add a short analysis description here
   class BABAR_2004_I656680 : public Analysis {
   public:
 
     /// Constructor
     DEFAULT_RIVET_ANALYSIS_CTOR(BABAR_2004_I656680);
 
 
     /// @name Analysis methods
     //@{
 
     /// Book histograms and initialise projections before the run
     void init() {
 
       // Initialise and register projections
       declare(FinalState(), "FS");
 
-      _num3pi = bookCounter("TMP/num3");
+      book(_num3pi, "TMP/num3");
 
     }
 
 
     /// Perform the per-event analysis
     void analyze(const Event& event) {
       const FinalState& fs = apply<FinalState>(event, "FS");
 
       map<long,int> nCount;
       int ntotal(0);
-      foreach (const Particle& p, fs.particles()) {
-	nCount[p.pdgId()] += 1;
+      for (const Particle& p : fs.particles()) {
+	nCount[p.pid()] += 1;
 	++ntotal;
       }
       if(ntotal!=3) vetoEvent;
       if(nCount[-211]==1&&nCount[211]==1&&nCount[111]==1)
-	_num3pi->fill(event.weight());
+	_num3pi->fill();
 
     }
 
 
     /// Normalise histograms etc., after the run
     void finalize() {
 
       double sigma = _num3pi->val();
       double error = _num3pi->err();
       sigma *= crossSection()/ sumOfWeights() /nanobarn;
       error *= crossSection()/ sumOfWeights() /nanobarn;
       Scatter2D temphisto(refData(1, 1, 1));
-      Scatter2DPtr  mult = bookScatter2D(1, 1, 1);
+      Scatter2DPtr  mult;
+      book(mult, 1, 1, 1);
       for (size_t b = 0; b < temphisto.numPoints(); b++) {
 	const double x  = temphisto.point(b).x();
 	pair<double,double> ex = temphisto.point(b).xErrs();
 	pair<double,double> ex2 = ex;
 	if(ex2.first ==0.) ex2. first=0.0001;
 	if(ex2.second==0.) ex2.second=0.0001;
 	if (inRange(sqrtS()/GeV, x-ex2.first, x+ex2.second)) {
 	  mult->addPoint(x, sigma, ex, make_pair(error,error));
 	}
 	else {
 	  mult->addPoint(x, 0., ex, make_pair(0.,.0));
 	}
       }
     }
 
     //@}
 
 
     /// @name Histograms
     //@{
     CounterPtr _num3pi;
     //@}
 
 
   };
 
 
   // The hook for the plugin system
   DECLARE_RIVET_PLUGIN(BABAR_2004_I656680);
 
 
 }
diff --git a/analyses/pluginBABAR/BABAR_2005_I676691.cc b/analyses/pluginBABAR/BABAR_2005_I676691.cc
--- a/analyses/pluginBABAR/BABAR_2005_I676691.cc
+++ b/analyses/pluginBABAR/BABAR_2005_I676691.cc
@@ -1,107 +1,108 @@
 // -*- C++ -*-
 #include "Rivet/Analysis.hh"
 #include "Rivet/Projections/FinalState.hh"
 
 namespace Rivet {
 
 
   /// @brief Add a short analysis description here
   class BABAR_2005_I676691 : public Analysis {
   public:
 
     /// Constructor
     DEFAULT_RIVET_ANALYSIS_CTOR(BABAR_2005_I676691);
 
 
     /// @name Analysis methods
     //@{
 
     /// Book histograms and initialise projections before the run
     void init() {
 
       // Initialise and register projections
       declare(FinalState(), "FS");
 
-      _c2pip2pim      = bookCounter("TMP/2pip2pim");
-      _cKpKmpippim  = bookCounter("TMP/KpKmpippim");
-      _c2Kp2Km      = bookCounter("TMP/2Kp2Km");
+      book(_c2pip2pim  , "TMP/2pip2pim");
+      book(_cKpKmpippim, "TMP/KpKmpippim");
+      book(_c2Kp2Km    , "TMP/2Kp2Km");
       
     }
 
 
     /// Perform the per-event analysis
     void analyze(const Event& event) {
       const FinalState& fs = apply<FinalState>(event, "FS");
 
       map<long,int> nCount;
       int ntotal(0);
-      foreach (const Particle& p, fs.particles()) {
-	nCount[p.pdgId()] += 1;
+      for (const Particle& p : fs.particles()) {
+	nCount[p.pid()] += 1;
 	++ntotal;
       }
 
       if(ntotal!=4) vetoEvent;
       
       if( nCount[211]==2 && nCount[-211]==2)
-	_c2pip2pim->fill(event.weight());
+	_c2pip2pim->fill();
       else if(nCount[321]==1 && nCount[-321]==1 && nCount[211]==1 && nCount[-211]==1)
-	_cKpKmpippim->fill(event.weight());
+	_cKpKmpippim->fill();
       else if( nCount[321]==2 && nCount[-321]==2)
-	_c2Kp2Km->fill(event.weight());
+	_c2Kp2Km->fill();
     }
     
     
     /// Normalise histograms etc., after the run
     void finalize() {
       
       for(unsigned int ix=1;ix<4;++ix) {
 	double sigma = 0., error = 0.;
 	if(ix==1) {
 	  sigma =  _c2pip2pim->val();
 	  error =  _c2pip2pim->err();
 	}
 	else if(ix==2) {
 	  sigma = _cKpKmpippim->val();
 	  error = _cKpKmpippim->err();
 	}
      	else if(ix==3) {
 	  sigma =  _c2Kp2Km->val();
 	  error =  _c2Kp2Km->err();
 	}
     	sigma *= crossSection()/ sumOfWeights() /nanobarn;
     	error *= crossSection()/ sumOfWeights() /nanobarn;
 	Scatter2D temphisto(refData(ix, 1, 1));
-	Scatter2DPtr  mult = bookScatter2D(ix, 1, 1);
+	Scatter2DPtr  mult;
+        book(mult, ix, 1, 1);
 	for (size_t b = 0; b < temphisto.numPoints(); b++) {
 	  const double x  = temphisto.point(b).x();
 	  pair<double,double> ex = temphisto.point(b).xErrs();
 	  pair<double,double> ex2 = ex;
 	  if(ex2.first ==0.) ex2. first=0.0001;
 	  if(ex2.second==0.) ex2.second=0.0001;
 	  if (inRange(sqrtS()/GeV, x-ex2.first, x+ex2.second)) {
 	    mult->addPoint(x, sigma, ex, make_pair(error,error));
 	  }
 	  else {
 	    mult->addPoint(x, 0., ex, make_pair(0.,.0));
 	  }
 	}
       }
     }
 
     //@}
 
 
     /// @name Histograms
     //@{
     CounterPtr _c2pip2pim, _cKpKmpippim, _c2Kp2Km;
     //@}
 
 
   };
 
 
   // The hook for the plugin system
   DECLARE_RIVET_PLUGIN(BABAR_2005_I676691);
 
 
 }
diff --git a/analyses/pluginBABAR/BABAR_2006_I700020.cc b/analyses/pluginBABAR/BABAR_2006_I700020.cc
--- a/analyses/pluginBABAR/BABAR_2006_I700020.cc
+++ b/analyses/pluginBABAR/BABAR_2006_I700020.cc
@@ -1,83 +1,84 @@
 // -*- C++ -*-
 #include "Rivet/Analysis.hh"
 #include "Rivet/Projections/FinalState.hh"
 
 namespace Rivet {
 
 
   /// @brief Add a short analysis description here
   class BABAR_2006_I700020 : public Analysis {
   public:
 
     /// Constructor
     DEFAULT_RIVET_ANALYSIS_CTOR(BABAR_2006_I700020);
 
 
     /// @name Analysis methods
     //@{
 
     /// Book histograms and initialise projections before the run
     void init() {
 
       // Initialise and register projections
       declare(FinalState(), "FS");
 
       // Book histograms
-      _nproton = bookCounter("TMP/proton");
+      book(_nproton, "TMP/proton");
     }
 
 
     /// Perform the per-event analysis
     void analyze(const Event& event) {
       const FinalState& fs = apply<FinalState>(event, "FS");
       if(fs.particles().size()!=2) vetoEvent;
-      foreach (const Particle& p, fs.particles()) {
-	if(abs(p.pdgId())!=PID::PROTON) vetoEvent;
+      for (const Particle& p : fs.particles()) {
+	if(abs(p.pid())!=PID::PROTON) vetoEvent;
       }
-      _nproton->fill(event.weight());
+      _nproton->fill();
     }
 
 
     /// Normalise histograms etc., after the run
     void finalize() {
 
       double sigma = _nproton->val();
       double error = _nproton->err();
       sigma *= crossSection()/ sumOfWeights() /picobarn;
       error *= crossSection()/ sumOfWeights() /picobarn;
       for(unsigned int ix=1;ix<3;++ix) {
 	Scatter2D temphisto(refData(ix, 1, 1));
-	Scatter2DPtr  mult = bookScatter2D(ix, 1, 1);
+	Scatter2DPtr mult;
+        book(mult, ix, 1, 1);
 	for (size_t b = 0; b < temphisto.numPoints(); b++) {
 	  const double x  = temphisto.point(b).x();
 	  pair<double,double> ex = temphisto.point(b).xErrs();
 	  pair<double,double> ex2 = ex;
 	  if(ex2.first ==0.) ex2. first=0.0001;
 	  if(ex2.second==0.) ex2.second=0.0001;
 	  if (inRange(sqrtS()/GeV, x-ex2.first, x+ex2.second)) {
 	    mult->addPoint(x, sigma, ex, make_pair(error,error));
 	  }
 	  else {
 	    mult->addPoint(x, 0., ex, make_pair(0.,.0));
 	  }
 	}
       }
     }
 
     //@}
 
 
     /// @name Histograms
     //@{
     CounterPtr _nproton;
     //@}
 
 
   };
 
 
   // The hook for the plugin system
   DECLARE_RIVET_PLUGIN(BABAR_2006_I700020);
 
 
 }
diff --git a/analyses/pluginBABAR/BABAR_2006_I709730.cc b/analyses/pluginBABAR/BABAR_2006_I709730.cc
--- a/analyses/pluginBABAR/BABAR_2006_I709730.cc
+++ b/analyses/pluginBABAR/BABAR_2006_I709730.cc
@@ -1,101 +1,102 @@
 // -*- C++ -*-
 #include "Rivet/Analysis.hh"
 #include "Rivet/Projections/FinalState.hh"
 
 
 namespace Rivet {
 
 
   /// @brief Add a short analysis description here
   class BABAR_2006_I709730 : public Analysis {
   public:
 
     /// Constructor
     DEFAULT_RIVET_ANALYSIS_CTOR(BABAR_2006_I709730);
 
 
     /// @name Analysis methods
     //@{
 
     /// Book histograms and initialise projections before the run
     void init() {
 
       // Initialise and register projections
       declare(FinalState(), "FS");
-      _num3pip3pim      = bookCounter("TMP/num3pip3pim"     );
-      _num2pip2pim2pi0  = bookCounter("TMP/num2pip2pim2pi0" );
-      _num2pip2pim2KpKm = bookCounter("TMP/num2pip2pim2KpKm");
+      book(_num3pip3pim,      "TMP/num3pip3pim"     );
+      book(_num2pip2pim2pi0,  "TMP/num2pip2pim2pi0" );
+      book(_num2pip2pim2KpKm, "TMP/num2pip2pim2KpKm");
     }
 
 
     /// Perform the per-event analysis
     void analyze(const Event& event) {
       const FinalState& fs = apply<FinalState>(event, "FS");
 
       map<long,int> nCount;
       int ntotal(0);
-      foreach (const Particle& p, fs.particles()) {
-	nCount[p.pdgId()] += 1;
+      for (const Particle& p : fs.particles()) {
+	nCount[p.pid()] += 1;
 	++ntotal;
       }
 
       if(ntotal!=6) vetoEvent;
       if(nCount[-211]==3 && nCount[211]==3)
-	_num3pip3pim->fill(event.weight());
+	_num3pip3pim->fill();
       else if(nCount[-211]==2 && nCount[211]==2 && nCount[111]==2)
-	_num2pip2pim2pi0->fill(event.weight());
+	_num2pip2pim2pi0->fill();
       else if(nCount[-211]==2 && nCount[211]==2 && nCount[321]==1 && nCount[-321]==1)
-	_num2pip2pim2KpKm->fill(event.weight());
+	_num2pip2pim2KpKm->fill();
     }
 
 
     /// Normalise histograms etc., after the run
     void finalize() {
 
       for(unsigned int ix=1; ix<4; ++ix) {
         double sigma = 0., error = 0.;
         if(ix==1) {
           sigma = _num3pip3pim->val();
           error = _num3pip3pim->err();
         }
         else if(ix==2) {
           sigma = _num2pip2pim2pi0->val();
           error = _num2pip2pim2pi0->err();
         }
         else if(ix==3) {
           sigma = _num2pip2pim2KpKm->val();
           error = _num2pip2pim2KpKm->err();
         }
         sigma *= crossSection()/ sumOfWeights() /nanobarn;
         error *= crossSection()/ sumOfWeights() /nanobarn;
         Scatter2D temphisto(refData(ix, 1, 1));
-        Scatter2DPtr  mult = bookScatter2D(ix, 1, 1);
+        Scatter2DPtr mult;
+        book(mult, ix, 1, 1);
         for (size_t b = 0; b < temphisto.numPoints(); b++) {
           const double x  = temphisto.point(b).x();
           pair<double,double> ex = temphisto.point(b).xErrs();
           pair<double,double> ex2 = ex;
           if(ex2.first ==0.) ex2. first=0.0001;
           if(ex2.second==0.) ex2.second=0.0001;
           if (inRange(sqrtS()/GeV, x-ex2.first, x+ex2.second)) {
             mult->addPoint(x, sigma, ex, make_pair(error,error));
           }
           else {
             mult->addPoint(x, 0., ex, make_pair(0.,.0));
           }
         }
       }
     }
 
     //@}
 
     // just count the number of events of the types we're looking for
     CounterPtr _num3pip3pim,_num2pip2pim2pi0,_num2pip2pim2KpKm;
     
   };
 
 
   // The hook for the plugin system
   DECLARE_RIVET_PLUGIN(BABAR_2006_I709730);
 
 
 }
diff --git a/analyses/pluginBABAR/BABAR_2006_I716277.cc b/analyses/pluginBABAR/BABAR_2006_I716277.cc
--- a/analyses/pluginBABAR/BABAR_2006_I716277.cc
+++ b/analyses/pluginBABAR/BABAR_2006_I716277.cc
@@ -1,132 +1,133 @@
 // -*- C++ -*-
 #include "Rivet/Analysis.hh"
 #include "Rivet/Projections/FinalState.hh"
 #include "Rivet/Projections/UnstableParticles.hh"
 
 namespace Rivet {
 
 
   /// @brief Add a short analysis description here
   class BABAR_2006_I716277 : public Analysis {
   public:
 
     /// Constructor
     DEFAULT_RIVET_ANALYSIS_CTOR(BABAR_2006_I716277);
 
 
     /// @name Analysis methods
     //@{
 
     /// Book histograms and initialise projections before the run
     void init() {
       // Initialise and register projections
       declare(FinalState(), "FS");
       declare(UnstableParticles(), "UFS");
-      _numEtaGamma = bookCounter("TMP/EtaGamma");
-      _numEtaPrimeGamma = bookCounter("TMP/EtaPrimeGamma");
+      book(_numEtaGamma, "TMP/EtaGamma");
+      book(_numEtaPrimeGamma, "TMP/EtaPrimeGamma");
     }
 
     void findChildren(const Particle & p,map<long,int> & nRes, int &ncount) {
-      foreach(const Particle &child, p.children()) {
+      for(const Particle &child: p.children()) {
 	if(child.children().empty()) {
-	  --nRes[child.pdgId()];
+	  --nRes[child.pid()];
 	  --ncount;
 	}
 	else
 	  findChildren(child,nRes,ncount);
       }
     }
 
     /// Perform the per-event analysis
     void analyze(const Event& event) {
 
       const FinalState& fs = apply<FinalState>(event, "FS");
       
       map<long,int> nCount;
       int ntotal(0);
-      foreach (const Particle& p, fs.particles()) {
-	nCount[p.pdgId()] += 1;
+      for (const Particle& p : fs.particles()) {
+	nCount[p.pid()] += 1;
 	++ntotal;
       }
       
       const FinalState& ufs = apply<FinalState>(event, "UFS");
-      foreach (const Particle& p, ufs.particles()) {
+      for (const Particle& p : ufs.particles()) {
 	if(p.children().empty()) continue;
 	// find the eta/eta prime
-        if(p.pdgId()!=221 && p.pdgId()!=331) continue;
+        if(p.pid()!=221 && p.pid()!=331) continue;
 	map<long,int> nRes = nCount;
 	int ncount = ntotal;
 	findChildren(p,nRes,ncount);
 	// eta pi+pi-
 	if(ncount!=1) continue;
 	bool matched = true;
 	for(auto const & val : nRes) {
 	  if(val.first==22) {
 	    if(val.second !=1) {
 	      matched = false;
 	      break;
 	    }
 	  }
 	  else if(val.second!=0) {
 	    matched = false;
 	    break;
 	  }
 	}
 	if(matched) {
-	  if(p.pdgId()==221)
-	    _numEtaGamma->fill(event.weight());
+	  if(p.pid()==221)
+	    _numEtaGamma->fill();
 	  else
-	    _numEtaPrimeGamma->fill(event.weight());
+	    _numEtaPrimeGamma->fill();
 	}
       }
     }
 
     /// Normalise histograms etc., after the run
     void finalize() {
       for(unsigned int ix=1;ix<3;++ix) {
 	double sigma,error;
 	if(ix==1) {
 	  sigma = _numEtaGamma->val();
 	  error = _numEtaGamma->err();
 	}
 	else {
 	  sigma = _numEtaPrimeGamma->val();
 	  error = _numEtaPrimeGamma->err();
 	}
 	sigma *= crossSection()/ sumOfWeights() /femtobarn;
 	error *= crossSection()/ sumOfWeights() /femtobarn; 
 	Scatter2D temphisto(refData(1, 1, ix));
-	Scatter2DPtr  mult = bookScatter2D(1, 1, ix);
+	Scatter2DPtr  mult;
+        book(mult, 1, 1, ix);
 	for (size_t b = 0; b < temphisto.numPoints(); b++) {
 	  const double x  = temphisto.point(b).x();
 	  pair<double,double> ex = temphisto.point(b).xErrs();
 	  pair<double,double> ex2 = ex;
 	  if(ex2.first ==0.) ex2. first=0.0001;
 	  if(ex2.second==0.) ex2.second=0.0001;
 	  if (inRange(sqrtS()/GeV, x-ex2.first, x+ex2.second)) {
 	    mult->addPoint(x, sigma, ex, make_pair(error,error));
 	  }
 	  else {
 	    mult->addPoint(x, 0., ex, make_pair(0.,.0));
 	  }
 	}
       }
     }
 
     //@}
 
 
     /// @name Histograms
     //@{
     CounterPtr _numEtaGamma,_numEtaPrimeGamma;
     //@}
 
 
   };
 
 
   // The hook for the plugin system
   DECLARE_RIVET_PLUGIN(BABAR_2006_I716277);
 
 
 }
diff --git a/analyses/pluginBABAR/BABAR_2006_I731865.cc b/analyses/pluginBABAR/BABAR_2006_I731865.cc
--- a/analyses/pluginBABAR/BABAR_2006_I731865.cc
+++ b/analyses/pluginBABAR/BABAR_2006_I731865.cc
@@ -1,117 +1,118 @@
 // -*- C++ -*-
 #include "Rivet/Analysis.hh"
 #include "Rivet/Projections/FinalState.hh"
 #include "Rivet/Projections/UnstableParticles.hh"
 
 namespace Rivet {
 
 
   /// @brief Add a short analysis description here
   class BABAR_2006_I731865 : public Analysis {
   public:
 
     /// Constructor
     DEFAULT_RIVET_ANALYSIS_CTOR(BABAR_2006_I731865);
 
 
     /// @name Analysis methods
     //@{
 
     /// Book histograms and initialise projections before the run
     void init() {
 
       // Initialise and register projections
       declare(FinalState(), "FS");
       declare(UnstableParticles(), "UFS");
 
-      _nPhiEta =  bookCounter("TMP/phieta");
+      book(_nPhiEta, "TMP/phieta");
     }
 
     void findChildren(const Particle & p,map<long,int> & nRes, int &ncount) {
-      foreach(const Particle &child, p.children()) {
+      for(const Particle &child : p.children()) {
 	if(child.children().empty()) {
-	  nRes[child.pdgId()]-=1;
+	  nRes[child.pid()]-=1;
 	  --ncount;
 	}
 	else
 	  findChildren(child,nRes,ncount);
       }
     }
 
     /// Perform the per-event analysis
     void analyze(const Event& event) {
       const FinalState& fs = apply<FinalState>(event, "FS");
 
       map<long,int> nCount;
       int ntotal(0);
-      foreach (const Particle& p, fs.particles()) {
-	nCount[p.pdgId()] += 1;
+      for (const Particle& p : fs.particles()) {
+	nCount[p.pid()] += 1;
 	++ntotal;
       }
       const FinalState& ufs = apply<FinalState>(event, "UFS");
-      foreach (const Particle& p, ufs.particles()) {
+      for (const Particle& p : ufs.particles()) {
 	if(p.children().empty()) continue;
-	if(p.pdgId()!=333) continue;
+	if(p.pid()!=333) continue;
 	map<long,int> nRes=nCount;
 	int ncount = ntotal;
 	findChildren(p,nRes,ncount);
-	foreach (const Particle& p2, ufs.particles()) {
-	  if(p2.pdgId()!=221) continue;
+	for (const Particle& p2 : ufs.particles()) {
+	  if(p2.pid()!=221) continue;
 	  if(p2.parents()[0].isSame(p)) continue;
 	  map<long,int> nResB = nRes;
 	  int ncountB = ncount;
 	  findChildren(p2,nResB,ncountB);
 	  if(ncountB!=0) continue;
 	  bool matched2 = true;
 	  for(auto const & val : nResB) {
 	    if(val.second!=0) {
 	      matched2 = false;
 	      break;
 	    }
 	  }
 	  if(matched2) {
-	    _nPhiEta->fill(event.weight());
+	    _nPhiEta->fill();
 	  }
 	}
       }
     }
 
 
     /// Normalise histograms etc., after the run
     void finalize() {
       double sigma = _nPhiEta->val();
       double error = _nPhiEta->err();
       sigma *= crossSection()/ sumOfWeights() /femtobarn;
       error *= crossSection()/ sumOfWeights() /femtobarn;
       
       Scatter2D temphisto(refData(1, 1, 2));
-      Scatter2DPtr  mult = bookScatter2D(1, 1, 2);
+      Scatter2DPtr  mult;
+      book(mult, 1, 1, 2);
       for (size_t b = 0; b < temphisto.numPoints(); b++) {
 	const double x  = temphisto.point(b).x();
 	pair<double,double> ex = temphisto.point(b).xErrs();
 	pair<double,double> ex2 = ex;
 	if(ex2.first ==0.) ex2. first=0.0001;
 	if(ex2.second==0.) ex2.second=0.0001;
 	if (inRange(sqrtS()/GeV, x-ex2.first, x+ex2.second)) {
 	  mult->addPoint(x, sigma, ex, make_pair(error,error));
 	}
 	else {
 	  mult->addPoint(x, 0., ex, make_pair(0.,.0));
 	}
       }
     }
 
     //@}
 
     /// @name Histograms
     //@{
     CounterPtr _nPhiEta;
     //@}
 
   };
 
 
   // The hook for the plugin system
   DECLARE_RIVET_PLUGIN(BABAR_2006_I731865);
 
 }
diff --git a/analyses/pluginBABAR/BABAR_2007_I729388.cc b/analyses/pluginBABAR/BABAR_2007_I729388.cc
--- a/analyses/pluginBABAR/BABAR_2007_I729388.cc
+++ b/analyses/pluginBABAR/BABAR_2007_I729388.cc
@@ -1,118 +1,119 @@
 // -*- C++ -*-
 #include "Rivet/Analysis.hh"
 #include "Rivet/Projections/FinalState.hh"
 #include "Rivet/Projections/UnstableParticles.hh"
 
 namespace Rivet {
 
 
   /// @brief Add a short analysis description here
   class BABAR_2007_I729388 : public Analysis {
   public:
 
     /// Constructor
     DEFAULT_RIVET_ANALYSIS_CTOR(BABAR_2007_I729388);
 
 
     /// @name Analysis methods
     //@{
 
     /// Book histograms and initialise projections before the run
     void init() {
       declare(FinalState(), "FS");
       declare(UnstableParticles(), "UFS");
-      _nPsi2s = bookCounter("TMP/psi2s");
+      book(_nPsi2s, "TMP/psi2s");
     }
 
     void findChildren(const Particle & p,map<long,int> & nRes, int &ncount) {
-      foreach(const Particle &child, p.children()) {
+      for(const Particle &child : p.children()) {
 	if(child.children().empty()) {
-	  --nRes[child.pdgId()];
+	  --nRes[child.pid()];
 	  --ncount;
 	}
 	else
 	  findChildren(child,nRes,ncount);
       }
     }
 
     /// Perform the per-event analysis
     void analyze(const Event& event) {
       const FinalState& fs = apply<FinalState>(event, "FS");
       map<long,int> nCount;
       int ntotal(0);
-      foreach (const Particle& p, fs.particles()) {
-	nCount[p.pdgId()] += 1;
+      for (const Particle& p : fs.particles()) {
+	nCount[p.pid()] += 1;
 	++ntotal;
       }
       const FinalState& ufs = apply<FinalState>(event, "UFS");
-      foreach (const Particle& p, ufs.particles()) {
+      for (const Particle& p : ufs.particles()) {
 	if(p.children().empty()) continue;
 	// find the psi(2S)
-	if(p.pdgId()==100443) {
+	if(p.pid()==100443) {
 	  map<long,int> nRes = nCount;
 	  int ncount = ntotal;
 	  findChildren(p,nRes,ncount);
 	  // omega pi+pi-
 	  if(ncount!=2) continue;
 	  bool matched = true;
 	  for(auto const & val : nRes) {
 	    if(abs(val.first)==211) {
 	      if(val.second !=1) {
 		matched = false;
 		break;
 	      }
 	    }
 	    else if(val.second!=0) {
 	      matched = false;
 	      break;
 	    }
 	  }
 	  if(matched) {
-	    _nPsi2s->fill(event.weight());
+	    _nPsi2s->fill();
 	    break;
 	  }
 	}
       }
     }
 
 
     /// Normalise histograms etc., after the run
     void finalize() {
       double sigma =  _nPsi2s->val();
       double error = _nPsi2s->err();
       sigma *= crossSection()/ sumOfWeights() /picobarn;
       error *= crossSection()/ sumOfWeights() /picobarn; 
       Scatter2D temphisto(refData(1, 1, 1));
-      Scatter2DPtr  mult = bookScatter2D(1, 1, 1);
+      Scatter2DPtr  mult;
+      book(mult, 1, 1, 1);
       for (size_t b = 0; b < temphisto.numPoints(); b++) {
 	const double x  = temphisto.point(b).x();
 	pair<double,double> ex = temphisto.point(b).xErrs();
 	pair<double,double> ex2 = ex;
 	if(ex2.first ==0.) ex2. first=0.0001;
 	if(ex2.second==0.) ex2.second=0.0001;
 	if (inRange(sqrtS()/GeV, x-ex2.first, x+ex2.second)) {
 	  mult->addPoint(x, sigma, ex, make_pair(error,error));
 	}
 	else {
 	  mult->addPoint(x, 0., ex, make_pair(0.,.0));
 	}
       }
     }
 
     //@}
 
 
     /// @name Histograms
     //@{
     CounterPtr _nPsi2s;
     //@}
 
 
   };
 
 
   // The hook for the plugin system
   DECLARE_RIVET_PLUGIN(BABAR_2007_I729388);
 
 
 }
diff --git a/analyses/pluginBABAR/BABAR_2007_I747875.cc b/analyses/pluginBABAR/BABAR_2007_I747875.cc
--- a/analyses/pluginBABAR/BABAR_2007_I747875.cc
+++ b/analyses/pluginBABAR/BABAR_2007_I747875.cc
@@ -1,210 +1,211 @@
 // -*- C++ -*-
 #include "Rivet/Analysis.hh"
 #include "Rivet/Projections/UnstableParticles.hh"
 #include "Rivet/Projections/FinalState.hh"
 
 
 namespace Rivet {
 
 
   /// @brief Add a short analysis description here
   class BABAR_2007_I747875 : public Analysis {
   public:
 
     /// Constructor
     DEFAULT_RIVET_ANALYSIS_CTOR(BABAR_2007_I747875);
 
 
     /// @name Analysis methods
     //@{
 
     /// Book histograms and initialise projections before the run
     void init() {
 
       // Initialise and register projections
       declare(FinalState(), "FS");
       declare(UnstableParticles(), "UFS");
 
-      _cKpKmpippim  = bookCounter("TMP/KpKmpippim");
-      _cKstarKpi    = bookCounter("TMP/KstarKpi");
-      _cphipippim   = bookCounter("TMP/phipippim");
-      _cphif0       = bookCounter("TMP/phif0");
-      _cKpKmpi0pi0  = bookCounter("TMP/KpKmpi0pi0");
-      _cphif0pi0pi0 = bookCounter("TMP/phif0pi0pi0");
-      _c2Kp2Km      = bookCounter("TMP/2Kp2Km");
+      book(_cKpKmpippim  , "TMP/KpKmpippim");
+      book(_cKstarKpi    ,"TMP/KstarKpi");
+      book(_cphipippim   , "TMP/phipippim");
+      book(_cphif0       , "TMP/phif0");
+      book(_cKpKmpi0pi0  , "TMP/KpKmpi0pi0");
+      book(_cphif0pi0pi0 , "TMP/phif0pi0pi0");
+      book(_c2Kp2Km      , "TMP/2Kp2Km");
       
     } 
 
     void findChildren(const Particle & p,map<long,int> & nRes, int &ncount) {
-      foreach(const Particle &child, p.children()) {
+      for(const Particle &child : p.children()) {
 	if(child.children().empty()) {
-	  nRes[child.pdgId()]-=1;
+	  nRes[child.pid()]-=1;
 	  --ncount;
 	}
 	else
 	  findChildren(child,nRes,ncount);
       }
     }
     
     /// Perform the per-event analysis
     void analyze(const Event& event) {
       const FinalState& fs = apply<FinalState>(event, "FS");
 
       map<long,int> nCount;
       int ntotal(0);
-      foreach (const Particle& p, fs.particles()) {
-	nCount[p.pdgId()] += 1;
+      for (const Particle& p : fs.particles()) {
+	nCount[p.pid()] += 1;
 	++ntotal;
       }
       const FinalState& ufs = apply<FinalState>(event, "UFS");
-      foreach (const Particle& p, ufs.particles()) {
+      for (const Particle& p : ufs.particles()) {
 	if(p.children().empty()) continue;
 	// K*0
-	if(abs(p.pdgId())==313) {
+	if(abs(p.pid())==313) {
 	  map<long,int> nRes=nCount;
 	  int ncount = ntotal;
 	  findChildren(p,nRes,ncount);
 	  // K* K+/- pi-/+
 	  if(ncount !=2 ) continue;
 	  bool matched = true;
 	  for(auto const & val : nRes) {
 	    if(abs(val.first)==321 || abs(val.first)==211) {
 	      continue;
 	    }
 	    else if(val.second!=0) {
 	      matched = false;
 	      break;
 	    }
 	  }
 	  if(matched==false) continue;
 	  if((nCount[321] == 1 && nCount[-321] ==0 &&
 	      nCount[211] == 0 && nCount[-211] == 1) ||
 	     (nCount[321] == 0 && nCount[-321] ==1 &&
 	      nCount[211] == 1 && nCount[-211] == 0))
-	    _cKstarKpi->fill(event.weight());
+	    _cKstarKpi->fill();
 	}
-	else if(p.pdgId()==333) {
+	else if(p.pid()==333) {
 	  map<long,int> nRes=nCount;
 	  int ncount = ntotal;
 	  findChildren(p,nRes,ncount);
 	  // phi pi+pi-
 	  if(ncount==2) {
 	    bool matched = true;
 	    for(auto const & val : nRes) {
 	      if(abs(val.first)==211) {
 		if(val.second!=1) {
 		  matched = false;
 		  break;
 		}
 	      }
 	      else if(val.second!=0) {
 		matched = false;
 		break;
 	      }
 	    }
 	    if(matched)
-	      _cphipippim->fill(event.weight());
+	      _cphipippim->fill();
 	  }
-	  foreach (const Particle& p2, ufs.particles()) {
-	    if(p2.pdgId()!=9010221) continue;
+	  for (const Particle& p2 : ufs.particles()) {
+	    if(p2.pid()!=9010221) continue;
 	    if(p2.parents()[0].isSame(p)) continue;
 	    map<long,int> nResB = nRes;
 	    int ncountB = ncount;
 	    findChildren(p2,nResB,ncountB);
 	    if(ncountB!=0) continue;
 	    bool matched2 = true;
 	    for(auto const & val : nResB) {
 	      if(val.second!=0) {
 		matched2 = false;
 		break;
 	      }
 	    }
 	    if(matched2) {
-	      _cphif0pi0pi0->fill(event.weight());
-	      _cphif0      ->fill(event.weight());
+	      _cphif0pi0pi0->fill();
+	      _cphif0      ->fill();
 	    }
 	  }
 	}
       }
       if(ntotal==4) {
 	if(nCount[321]==1 && nCount[-321]==1 && nCount[211]==1 && nCount[-211]==1)
-	  _cKpKmpippim->fill(event.weight());
+	  _cKpKmpippim->fill();
 	else if( nCount[321]==1 && nCount[-321]==1 && nCount[111]==2)
-	  _cKpKmpi0pi0->fill(event.weight());
+	  _cKpKmpi0pi0->fill();
 	else if( nCount[321]==2 && nCount[-321]==2)
-	  _c2Kp2Km->fill(event.weight());
+	  _c2Kp2Km->fill();
       }
     }
 
 
     /// Normalise histograms etc., after the run
     void finalize() {
       for(unsigned int ix=1; ix<8; ++ix) {
         double sigma = 0., error = 0.;
         if(ix==1) {
           sigma = _cKpKmpippim->val();
           error = _cKpKmpippim->err();
         }
         else if(ix==2) {
           sigma = _cKstarKpi->val();
           error = _cKstarKpi->err();
         }
         else if(ix==3) {
           sigma = _cphipippim->val();
           error = _cphipippim->err();
         }
         else if(ix==4) {
           sigma = _cphif0->val();
           error = _cphif0->err();
         }
         else if(ix==5) {
           sigma = _cKpKmpi0pi0->val();
           error = _cKpKmpi0pi0->err();
         }
         else if(ix==6) {
           sigma = _cphif0pi0pi0->val();
           error = _cphif0pi0pi0->err();
         }
         else if(ix==7) {
           sigma =  _c2Kp2Km->val();
           error =  _c2Kp2Km->err();
         }
     	sigma *= crossSection()/ sumOfWeights() /nanobarn;
     	error *= crossSection()/ sumOfWeights() /nanobarn;
 
 	Scatter2D temphisto(refData(ix, 1, 1));
-	Scatter2DPtr  mult = bookScatter2D(ix, 1, 1);
+	Scatter2DPtr  mult;
+        book(mult, ix, 1, 1);
 	for (size_t b = 0; b < temphisto.numPoints(); b++) {
 	  const double x  = temphisto.point(b).x();
 	  pair<double,double> ex = temphisto.point(b).xErrs();
 	  pair<double,double> ex2 = ex;
 	  if(ex2.first ==0.) ex2. first=0.0001;
 	  if(ex2.second==0.) ex2.second=0.0001;
 	  if (inRange(sqrtS()/GeV, x-ex2.first, x+ex2.second)) {
 	    mult->addPoint(x, sigma, ex, make_pair(error,error));
 	  }
 	  else {
 	    mult->addPoint(x, 0., ex, make_pair(0.,.0));
 	  }
 	}
       }
     }
 
     //@}
 
 
     /// @name Histograms
     //@{
     CounterPtr _cKpKmpippim, _cKstarKpi, _cphipippim,
       _cphif0, _cKpKmpi0pi0, _cphif0pi0pi0, _c2Kp2Km;
     //@}
 
 
   };
 
 
   // The hook for the plugin system
   DECLARE_RIVET_PLUGIN(BABAR_2007_I747875);
 
 
 }
diff --git a/analyses/pluginBABAR/BABAR_2007_I758568.cc b/analyses/pluginBABAR/BABAR_2007_I758568.cc
--- a/analyses/pluginBABAR/BABAR_2007_I758568.cc
+++ b/analyses/pluginBABAR/BABAR_2007_I758568.cc
@@ -1,258 +1,259 @@
 // -*- C++ -*-
 #include "Rivet/Analysis.hh"
 #include "Rivet/Projections/FinalState.hh"
 #include "Rivet/Projections/UnstableParticles.hh"
 
 namespace Rivet {
 
 
   /// @brief Add a short analysis description here
   class BABAR_2007_I758568 : public Analysis {
   public:
 
     /// Constructor
     DEFAULT_RIVET_ANALYSIS_CTOR(BABAR_2007_I758568);
 
 
     /// @name Analysis methods
     //@{
 
     /// Book histograms and initialise projections before the run
     void init() {
 
       // Initialise and register projections
       declare(FinalState(), "FS");
       declare(UnstableParticles(), "UFS");
 
       // Book histograms
       for(unsigned int ix=1;ix<12;++ix) {
 	stringstream ss;
 	ss << "TMP/n" << ix;
-	_nMeson[ix]= bookCounter(ss.str());
+	book(_nMeson[ix], ss.str());
       }
     }
 
 
     void findChildren(const Particle & p,map<long,int> & nRes, int &ncount) {
-      foreach(const Particle &child, p.children()) {
+      for(const Particle &child : p.children()) {
 	if(child.children().empty()) {
-	  nRes[child.pdgId()]-=1;
+	  nRes[child.pid()]-=1;
 	  --ncount;
 	}
 	else
 	  findChildren(child,nRes,ncount);
       }
     }
 
     /// Perform the per-event analysis
     void analyze(const Event& event) {
       const FinalState& fs = apply<FinalState>(event, "FS");
 
       map<long,int> nCount;
       int ntotal(0);
-      foreach (const Particle& p, fs.particles()) {
-	nCount[p.pdgId()] += 1;
+      for (const Particle& p : fs.particles()) {
+	nCount[p.pid()] += 1;
 	++ntotal;
       }
       const FinalState& ufs = apply<FinalState>(event, "UFS");
-      foreach (const Particle& p, ufs.particles()) {
+      for (const Particle& p : ufs.particles()) {
 	if(p.children().empty()) continue;
-	if(p.pdgId()!=223 && p.pdgId()!=221&&p.pdgId()!=331&& p.pdgId()!=20223)
+	if(p.pid()!=223 && p.pid()!=221&&p.pid()!=331&& p.pid()!=20223)
 	  continue;
 	map<long,int> nRes = nCount;
 	int ncount = ntotal;
 	findChildren(p,nRes,ncount);
 	// omega
-	if(p.pdgId()==223) {
+	if(p.pid()==223) {
 	  if(ncount==2) {
 	    bool matched = true;
 	    for(auto const & val : nRes) {
 	      if(abs(val.first)==211) {
 		if(val.second!=1) {
 		  matched = false;
 		  break;
 		}
 	      }
 	      else if(val.second!=0) {
 		matched = false;
 		break;
 	      }
 	    }
 	    if(matched)
-	      _nMeson[3]->fill(event.weight());matched = true;
+	      _nMeson[3]->fill();matched = true;
 	    for(auto const & val : nRes) {
 	      if(abs(val.first)==321) {
 		if(val.second!=1) {
 		  matched = false;
 		  break;
 		}
 	      }
 	      else if(val.second!=0) {
 		matched = false;
 		break;
 	      }
 	    }
 	    if(matched)
-	      _nMeson[10]->fill(event.weight());
+	      _nMeson[10]->fill();
 	  }
-	  foreach (const Particle& p2, ufs.particles()) {
-	    if(p2.pdgId()!=9010221) continue;
+	  for (const Particle& p2 : ufs.particles()) {
+	    if(p2.pid()!=9010221) continue;
 	    if(p2.parents()[0].isSame(p)) continue;
 	    map<long,int> nResB = nRes;
 	    int ncountB = ncount;
 	    findChildren(p2,nResB,ncountB);
 	    if(ncountB!=0) continue;
 	    bool matched2 = true;
 	    for(auto const & val : nResB) {
 	      if(val.second!=0) {
 		matched2 = false;
 		break;
 	      }
 	    }
 	    if(matched2)
-	      _nMeson[4]->fill(event.weight());
+	      _nMeson[4]->fill();
 	  }
 	}
-	else if(p.pdgId()==221) {
+	else if(p.pid()==221) {
 	  if(ncount==2) {
 	    bool matched = true;
 	    for(auto const & val : nRes) {
 	      if(abs(val.first)==211) {
 		if(val.second!=1) {
 		  matched = false;
 		  break;
 		}
 	      }
 	      else if(val.second!=0) {
 		matched = false;
 		break;
 	      }
 	    }
 	    if(matched)
-	      _nMeson[2]->fill(event.weight());
+	      _nMeson[2]->fill();
 	  }
 	  else if(ncount==4) {
 	    bool matched = true;
 	    for(auto const & val : nRes) {
 	      if(abs(val.first)==211) {
 		if(val.second!=2) {
 		  matched = false;
 		  break;
 		}
 	      }
 	      else if(val.second!=0) {
 		matched = false;
 		break;
 	      }
 	    }
 	    if(matched)
-	      _nMeson[5]->fill(event.weight());
+	      _nMeson[5]->fill();
 	    matched=true;
 	    for(auto const & val : nRes) {
 	      if(abs(val.first)==211 || abs(val.first)==321) {
 		if(val.second!=1) {
 		  matched = false;
 		  break;
 		}
 	      }
 	      else if(val.second!=0) {
 		matched = false;
 		break;
 	      }
 	    }
 	    if(matched)
-	      _nMeson[11]->fill(event.weight());
+	      _nMeson[11]->fill();
 	  }
-	  foreach(const Particle& p2, ufs.particles()) {
-	    if(p2.pdgId()!=333) continue;
+	  for(const Particle& p2 : ufs.particles()) {
+	    if(p2.pid()!=333) continue;
 	    map<long,int> nResB = nRes;
 	    int ncountB = ncount;
 	    findChildren(p2,nResB,ncountB);
 	    if(ncountB!=0) continue;
 	    bool matched2 = true;
 	    for(auto const & val : nResB) {
 	      if(val.second!=0) {
 		matched2 = false;
 		break;
 	      }
 	    }
 	    if(matched2)
-	      _nMeson[9]->fill(event.weight());
+	      _nMeson[9]->fill();
 	  }
 	}
-	else if(p.pdgId()==331 || p.pdgId()==20223) {
+	else if(p.pid()==331 || p.pid()==20223) {
 	  if(ncount!=2) continue;
 	  bool matched = true;
 	  for(auto const & val : nRes) {
 	    if(abs(val.first)==211) {
 	      if(val.second!=1) {
 		matched = false;
 		break;
 	      }
 	    }
 	    else if(val.second!=0) {
 	      matched = false;
 	      break;
 	    }
 	  }
 	  if(matched) {
-	    if(p.pdgId()==331)
-	      _nMeson[6]->fill(event.weight());
+	    if(p.pid()==331)
+	      _nMeson[6]->fill();
 	    else
-	      _nMeson[7]->fill(event.weight());
+	      _nMeson[7]->fill();
 	  }
 	}
       }
 
       if(ntotal==5) {
 	if(nCount[211]==2&&nCount[-211]==2&&nCount[111]==1)
-	  _nMeson[1]->fill(event.weight());
+	  _nMeson[1]->fill();
 	else if(nCount[321]==1&&nCount[-321]==1&&
 		nCount[211]==1&&nCount[-211]==1&&nCount[111]==1)
-	  _nMeson[8]->fill(event.weight());
+	  _nMeson[8]->fill();
       }
     }
 
 
     /// Normalise histograms etc., after the run
     void finalize() {
       for(unsigned int ix=1;ix<12;++ix) {
 	double sigma = _nMeson[ix]->val();
 	double error = _nMeson[ix]->err();
     	sigma *= crossSection()/ sumOfWeights() /nanobarn;
     	error *= crossSection()/ sumOfWeights() /nanobarn; 
 	Scatter2D temphisto(refData(ix, 1, 1));
-	Scatter2DPtr  mult = bookScatter2D(ix, 1, 1);
+	Scatter2DPtr  mult;
+        book(mult, ix, 1, 1);
 	for (size_t b = 0; b < temphisto.numPoints(); b++) {
 	  const double x  = temphisto.point(b).x();
 	  pair<double,double> ex = temphisto.point(b).xErrs();
 	  pair<double,double> ex2 = ex;
 	  if(ex2.first ==0.) ex2. first=0.0001;
 	  if(ex2.second==0.) ex2.second=0.0001;
 	  if (inRange(sqrtS()/GeV, x-ex2.first, x+ex2.second)) {
 	    mult->addPoint(x, sigma, ex, make_pair(error,error));
 	  }
 	  else {
 	    mult->addPoint(x, 0., ex, make_pair(0.,.0));
 	  }
 	}
       }
     }
 
     //@}
 
 
     /// @name Histograms
     //@{
     CounterPtr _nMeson[12];
     //@}
 
 
   };
 
 
   // The hook for the plugin system
   DECLARE_RIVET_PLUGIN(BABAR_2007_I758568);
 
 
 }
diff --git a/analyses/pluginBABAR/BABAR_2007_I760730.cc b/analyses/pluginBABAR/BABAR_2007_I760730.cc
--- a/analyses/pluginBABAR/BABAR_2007_I760730.cc
+++ b/analyses/pluginBABAR/BABAR_2007_I760730.cc
@@ -1,159 +1,160 @@
 // -*- C++ -*-
 #include "Rivet/Analysis.hh"
 #include "Rivet/Projections/FinalState.hh"
 #include "Rivet/Projections/UnstableParticles.hh"
 
 namespace Rivet {
 
 
   /// @brief Add a short analysis description here
   class BABAR_2007_I760730 : public Analysis {
   public:
 
     /// Constructor
     DEFAULT_RIVET_ANALYSIS_CTOR(BABAR_2007_I760730);
 
 
     /// @name Analysis methods
     //@{
 
     /// Book histograms and initialise projections before the run
     void init() {
       // Initialise and register projections
       declare(FinalState(), "FS");
       declare(UnstableParticles(), "UFS");
-      _nLL = bookCounter( "/TMP/nLL" );
-      _nSS = bookCounter( "/TMP/nSS" );
-      _nLS = bookCounter( "/TMP/nLS" );
+      book(_nLL, "/TMP/nLL" );
+      book(_nSS, "/TMP/nSS" );
+      book(_nLS, "/TMP/nLS" );
     }
 
     void findChildren(const Particle & p,map<long,int> & nRes, int &ncount) {
-      foreach(const Particle &child, p.children()) {
+      for(const Particle &child : p.children()) {
 	if(child.children().empty()) {
-	  nRes[child.pdgId()]-=1;
+	  nRes[child.pid()]-=1;
 	  --ncount;
 	}
 	else
 	  findChildren(child,nRes,ncount);
       }
     }
     
     /// Perform the per-event analysis
     void analyze(const Event& event) {
       const FinalState& fs = apply<FinalState>(event, "FS");
       // total hadronic and muonic cross sections
       map<long,int> nCount;
       int ntotal(0);
-      foreach (const Particle& p, fs.particles()) {
-	nCount[p.pdgId()] += 1;
+      for (const Particle& p : fs.particles()) {
+	nCount[p.pid()] += 1;
 	++ntotal;
       }
       
       // find the Lambdas and Sigmas
       const FinalState& ufs = apply<UnstableParticles>(event, "UFS");
       for(unsigned int ix=0;ix<ufs.particles().size();++ix) {
       	const Particle& p1 = ufs.particles()[ix];
-      	if(abs(p1.pdgId())!=3122&&abs(p1.pdgId())!=3212) continue;
+      	if(abs(p1.pid())!=3122&&abs(p1.pid())!=3212) continue;
       	bool matched = false;
       	// check fs
       	bool fs = true;
-      	foreach(const Particle & child, p1.children()) {
-      	  if(child.pdgId()==p1.pdgId()) {
+      	for(const Particle & child : p1.children()) {
+      	  if(child.pid()==p1.pid()) {
       	    fs = false;
       	    break;
       	  }
       	}
       	if(!fs) continue;
       	// find the children
       	map<long,int> nRes = nCount;
       	int ncount = ntotal;
       	findChildren(p1,nRes,ncount);
       	for(unsigned int iy=ix+1;iy<ufs.particles().size();++iy) {
       	  const Particle& p2 = ufs.particles()[iy];
-	  if(abs(p2.pdgId())!=3122&&abs(p2.pdgId())!=3212) continue;
+	  if(abs(p2.pid())!=3122&&abs(p2.pid())!=3212) continue;
 	  // check fs
 	  bool fs = true;
-	  foreach(const Particle & child, p2.children()) {
-	    if(child.pdgId()==p2.pdgId()) {
+	  for(const Particle & child : p2.children()) {
+	    if(child.pid()==p2.pid()) {
 	      fs = false;
 	      break;
 	    }
 	  }
 	  if(!fs) continue;
       	  map<long,int> nRes2 = nRes;
       	  int ncount2 = ncount;
       	  findChildren(p2,nRes2,ncount2);
       	  if(ncount2!=0) continue;
       	  matched=true;
       	  for(auto const & val : nRes2) {
       	    if(val.second!=0) {
       	      matched = false;
       	      break;
       	    }
       	  }
       	  if(matched) {
-	    if(abs(p1.pdgId())==3122 && abs(p2.pdgId())==3122)
-	      _nLL->fill(event.weight());
-	    else if(abs(p1.pdgId())==3212 && abs(p2.pdgId())==3212)
-	      _nSS->fill(event.weight());
+	    if(abs(p1.pid())==3122 && abs(p2.pid())==3122)
+	      _nLL->fill();
+	    else if(abs(p1.pid())==3212 && abs(p2.pid())==3212)
+	      _nSS->fill();
 	    else
-	      _nLS->fill(event.weight());
+	      _nLS->fill();
       	    break;
       	  }
       	}
       	if(matched) break;
       }
     }
 
     /// Normalise histograms etc., after the run
     void finalize() {
       double fact = crossSection()/ sumOfWeights() /picobarn;
       for(unsigned int ix=1;ix<4;++ix) {
 	double sigma,error;
 	if(ix==1) {
 	  sigma = _nLL->val()*fact;
 	  error = _nLL->err()*fact;
 	}
 	else if(ix==2) {
 	  sigma = _nSS->val()*fact;
 	  error = _nSS->err()*fact;
 	}
 	else {
 	  sigma = _nLS->val()*fact;
 	  error = _nLS->err()*fact;
 	}
 	Scatter2D temphisto(refData(ix, 1, 1));
-	Scatter2DPtr  mult = bookScatter2D(ix, 1, 1);
+	Scatter2DPtr  mult;
+        book(mult, ix, 1, 1);
 	for (size_t b = 0; b < temphisto.numPoints(); b++) {
 	  const double x  = temphisto.point(b).x();
 	  pair<double,double> ex = temphisto.point(b).xErrs();
 	  pair<double,double> ex2 = ex;
 	  if(ex2.first ==0.) ex2. first=0.0001;
 	  if(ex2.second==0.) ex2.second=0.0001;
 	  if (inRange(sqrtS()/GeV, x-ex2.first, x+ex2.second)) {
 	    mult->addPoint(x, sigma, ex, make_pair(error,error));
 	  }
 	  else {
 	    mult->addPoint(x, 0., ex, make_pair(0.,.0));
 	  }
 	}
       }
     }
 
     //@}
 
 
     /// @name Histograms
     //@{
     CounterPtr _nLL,_nSS,_nLS;
     //@}
 
 
   };
 
 
   // The hook for the plugin system
   DECLARE_RIVET_PLUGIN(BABAR_2007_I760730);
 
 
 }
diff --git a/analyses/pluginBABAR/BABAR_2007_S7266081.cc b/analyses/pluginBABAR/BABAR_2007_S7266081.cc
--- a/analyses/pluginBABAR/BABAR_2007_S7266081.cc
+++ b/analyses/pluginBABAR/BABAR_2007_S7266081.cc
@@ -1,184 +1,183 @@
 // -*- C++ -*-
 #include <iostream>
 #include "Rivet/Analysis.hh"
 #include "Rivet/Projections/UnstableParticles.hh"
 
 namespace Rivet {
 
 
   /// @brief BABAR tau lepton to three charged hadrons
   /// @author Peter Richardson
   class BABAR_2007_S7266081 : public Analysis {
   public:
 
     BABAR_2007_S7266081()
       : Analysis("BABAR_2007_S7266081")
     {   }
 
 
     void init() {
       declare(UnstableParticles(), "UFS");
 
       book(_hist_pipipi_pipipi , 1, 1, 1);
       book(_hist_pipipi_pipi   , 2, 1, 1);
       book(_hist_Kpipi_Kpipi   , 3, 1, 1);
       book(_hist_Kpipi_Kpi     , 4, 1, 1);
       book(_hist_Kpipi_pipi    , 5, 1, 1);
       book(_hist_KpiK_KpiK     , 6, 1, 1);
       book(_hist_KpiK_KK       , 7, 1, 1);
       book(_hist_KpiK_piK      , 8, 1, 1);
       book(_hist_KKK_KKK       , 9, 1, 1);
       book(_hist_KKK_KK        ,10, 1, 1);
 
       book(_weight_total, "weight_total");
       book(_weight_pipipi, "weight_pipipi");
       book(_weight_Kpipi, "weight_Kpipi");
       book(_weight_KpiK, "weight_KpiK");
       book(_weight_KKK, "weight_KKK");
 
       book(tmp11, 11, 1, 1, true);
       book(tmp12, 12, 1, 1, true);
       book(tmp13, 13, 1, 1, true);
       book(tmp14, 14, 1, 1, true);      
     }
 
 
     void analyze(const Event& e) {
-      double weight = e.weight();
       // Find the taus
       Particles taus;
       for(const Particle& p : apply<UnstableParticles>(e, "UFS").particles(Cuts::pid==PID::TAU)) {
         _weight_total->fill();
         Particles pip, pim, Kp, Km;
         unsigned int nstable = 0;
         // Find the decay products we want
         findDecayProducts(p, nstable, pip, pim, Kp, Km);
         if (p.pid() < 0) {
           swap(pip, pim);
           swap(Kp, Km );
         }
         if (nstable != 4) continue;
         // pipipi
         if (pim.size() == 2 && pip.size() == 1) {
           _weight_pipipi->fill();
           _hist_pipipi_pipipi->
             fill((pip[0].momentum()+pim[0].momentum()+pim[1].momentum()).mass());
           _hist_pipipi_pipi->
             fill((pip[0].momentum()+pim[0].momentum()).mass());
           _hist_pipipi_pipi->
             fill((pip[0].momentum()+pim[1].momentum()).mass());
         }
         else if (pim.size() == 1 && pip.size() == 1 && Km.size() == 1) {
           _weight_Kpipi->fill();
           _hist_Kpipi_Kpipi->
             fill((pim[0].momentum()+pip[0].momentum()+Km[0].momentum()).mass());
           _hist_Kpipi_Kpi->
             fill((pip[0].momentum()+Km[0].momentum()).mass());
           _hist_Kpipi_pipi->
             fill((pim[0].momentum()+pip[0].momentum()).mass());
         }
         else if (Kp.size() == 1 && Km.size() == 1 && pim.size() == 1) {
           _weight_KpiK->fill();
           _hist_KpiK_KpiK->
             fill((Kp[0].momentum()+Km[0].momentum()+pim[0].momentum()).mass());
           _hist_KpiK_KK->
             fill((Kp[0].momentum()+Km[0].momentum()).mass());
           _hist_KpiK_piK->
             fill((Kp[0].momentum()+pim[0].momentum()).mass());
         }
         else if (Kp.size() == 1 && Km.size() == 2) {
           _weight_KKK->fill();
           _hist_KKK_KKK->
             fill((Kp[0].momentum()+Km[0].momentum()+Km[1].momentum()).mass());
           _hist_KKK_KK->
             fill((Kp[0].momentum()+Km[0].momentum()).mass());
           _hist_KKK_KK->
             fill((Kp[0].momentum()+Km[1].momentum()).mass());
         }
       }
     }
 
 
     void finalize() {
       if (_weight_pipipi->val() > 0.) {
         scale(_hist_pipipi_pipipi, 1.0 / *_weight_pipipi);
         scale(_hist_pipipi_pipi  , 0.5 / *_weight_pipipi);
       }
       if (_weight_Kpipi->val() > 0.) {
         scale(_hist_Kpipi_Kpipi  , 1.0 / *_weight_Kpipi);
         scale(_hist_Kpipi_Kpi    , 1.0 / *_weight_Kpipi);
         scale(_hist_Kpipi_pipi   , 1.0 / *_weight_Kpipi);
       }
       if (_weight_KpiK->val() > 0.) {
         scale(_hist_KpiK_KpiK    , 1.0 / *_weight_KpiK);
         scale(_hist_KpiK_KK      , 1.0 / *_weight_KpiK);
         scale(_hist_KpiK_piK     , 1.0 / *_weight_KpiK);
       }
       if (_weight_KKK->val() > 0.) {
         scale(_hist_KKK_KKK      , 1.0 / *_weight_KKK);
         scale(_hist_KKK_KK       , 0.5 / *_weight_KKK);
       }
       tmp11->point(0).setY(100*_weight_pipipi->val()/_weight_total->val(), 100*sqrt(double(_weight_pipipi->val()))/_weight_total->val());
       tmp12->point(0).setY(100*_weight_Kpipi->val()/_weight_total->val(), 100*sqrt(double(_weight_Kpipi->val()))/_weight_total->val());
       tmp13->point(0).setY(100*_weight_KpiK->val()/_weight_total->val(), 100*sqrt(double(_weight_KpiK->val()))/_weight_total->val());
       tmp14->point(0).setY(100*_weight_KKK->val()/_weight_total->val(), 100*sqrt(double(_weight_KKK->val()))/_weight_total->val());
     }
 
 
   private:
 
     //@{
     Scatter2DPtr tmp11, tmp12, tmp13, tmp14;
  
     // Histograms
     Histo1DPtr _hist_pipipi_pipipi, _hist_pipipi_pipi;
     Histo1DPtr _hist_Kpipi_Kpipi, _hist_Kpipi_Kpi, _hist_Kpipi_pipi;
     Histo1DPtr _hist_KpiK_KpiK, _hist_KpiK_KK, _hist_KpiK_piK;
     Histo1DPtr _hist_KKK_KKK, _hist_KKK_KK;
 
     // Weights counters
     CounterPtr _weight_total, _weight_pipipi, _weight_Kpipi, _weight_KpiK, _weight_KKK;
 
     //@}
 
     void findDecayProducts(const Particle &mother,
                            unsigned int & nstable,
                            Particles& pip, Particles& pim,
                            Particles& Kp, Particles& Km) {
       for (const Particle &p : mother.children()) {
-        long id = p.pdgId();
+        long id = p.pid();
         if (id == PID::PI0 )
           ++nstable;
         else if (id == PID::K0S)
           ++nstable;
         else if (id == PID::PIPLUS) {
           pip.push_back(p);
           ++nstable;
         }
         else if (id == PID::PIMINUS) {
           pim.push_back(p);
           ++nstable;
         }
         else if (id == PID::KPLUS) {
           Kp.push_back(p);
           ++nstable;
         }
         else if (id == PID::KMINUS) {
           Km.push_back(p);
           ++nstable;
         }
         else if (!p.children().empty()) {
           findDecayProducts(p, nstable, pip, pim, Kp, Km);
         }
         else  ++nstable;
       }
     }
 
 
   };
 
 
   // The hook for the plugin system
   DECLARE_RIVET_PLUGIN(BABAR_2007_S7266081);
 
 }
diff --git a/analyses/pluginBABAR/BABAR_2008_I765258.cc b/analyses/pluginBABAR/BABAR_2008_I765258.cc
--- a/analyses/pluginBABAR/BABAR_2008_I765258.cc
+++ b/analyses/pluginBABAR/BABAR_2008_I765258.cc
@@ -1,175 +1,176 @@
 // -*- C++ -*-
 #include "Rivet/Analysis.hh"
 #include "Rivet/Projections/FinalState.hh"
 #include "Rivet/Projections/UnstableParticles.hh"
 
 namespace Rivet {
 
 
   /// @brief Add a short analysis description here
   class BABAR_2008_I765258 : public Analysis {
   public:
 
     /// Constructor
     DEFAULT_RIVET_ANALYSIS_CTOR(BABAR_2008_I765258);
 
 
     /// @name Analysis methods
     //@{
 
     /// Book histograms and initialise projections before the run
     void init() {
 
       // Initialise and register projections
       declare(FinalState(), "FS");
       declare(UnstableParticles(), "UFS");
 
       // Book histograms
       for(unsigned int ix=1;ix<6;++ix) {
 	stringstream ss;
 	ss << "TMP/n" << ix;
-	_nMeson[ix]= bookCounter(ss.str());
+	book(_nMeson[ix], ss.str());
       }
 
     }
 
     void findChildren(const Particle & p,map<long,int> & nRes, int &ncount) {
-      foreach(const Particle &child, p.children()) {
+      for (const Particle &child : p.children()) {
 	if(child.children().empty()) {
-	  nRes[child.pdgId()]-=1;
+	  nRes[child.pid()]-=1;
 	  --ncount;
 	}
 	else
 	  findChildren(child,nRes,ncount);
       }
     }
     
     /// Perform the per-event analysis
     void analyze(const Event& event) {
       const FinalState& fs = apply<FinalState>(event, "FS");
 
       map<long,int> nCount;
       int ntotal(0);
-      foreach (const Particle& p, fs.particles()) {
-	nCount[p.pdgId()] += 1;
+      for (const Particle& p : fs.particles()) {
+	nCount[p.pid()] += 1;
 	++ntotal;
       }
       const FinalState& ufs = apply<FinalState>(event, "UFS");
       
-      foreach (const Particle& p, ufs.particles()) {
+      for (const Particle& p : ufs.particles()) {
 	if(p.children().empty()) continue;
-	if(p.pdgId()!=221 && p.pdgId()!=333) continue;
+	if(p.pid()!=221 && p.pid()!=333) continue;
 	map<long,int> nRes = nCount;
 	int ncount = ntotal;
 	findChildren(p,nRes,ncount);
 	  
-	if(p.pdgId()==221) {
+	if(p.pid()==221) {
 	  bool matchedKK = false;
 	  if(ncount==2) {
 	    matchedKK = true;
 	    for(auto const & val : nRes) {
 	      if(abs(val.first)==321) {
 		if(val.second!=1) {
 		  matchedKK = false;
 		  break;
 		}
 	      }
 	      else if(val.second!=0) {
 		matchedKK = false;
 		break;
 	      }
 	    }
 	  }
-	  foreach (const Particle& p2, ufs.particles()) {
-	    if(p2.pdgId()!=333) continue;
+	  for (const Particle& p2 : ufs.particles()) {
+	    if(p2.pid()!=333) continue;
 	    if(p2.parents()[0].isSame(p)) continue;
 	    map<long,int> nResB = nRes;
 	    int ncountB = ncount;
 	    findChildren(p2,nResB,ncountB);
 	    if(ncountB!=0) continue;
 	    bool matched2 = true;
 	    for(auto const & val : nResB) {
 	      if(val.second!=0) {
 		matched2 = false;
 		break;
 	      }
 	    }
 	    if(matched2)
-	      _nMeson[5]->fill(event.weight());
+	      _nMeson[5]->fill();
 	    else if(matchedKK)
-	      _nMeson[4]->fill(event.weight());
+	      _nMeson[4]->fill();
 	  }
 	}
-	else if(p.pdgId()==333) {
+	else if(p.pid()==333) {
 	  if(ncount!=1) continue;
 	  bool matched = true;
 	  for(auto const & val : nRes) {
 	    if(val.first==111) {
 	      if(val.second!=1) {
 		matched = false;
 		break;
 	      }
 	    }
 	    else if(val.second!=0) {
 	      matched = false;
 	      break;
 	    }
 	  }
 	  if(matched)
-	    _nMeson[3]->fill(event.weight());
+	    _nMeson[3]->fill();
 	}
       }
 
 
       if(ntotal==3 && nCount[310]==1 &&
 	 ((nCount[ 211]==1&&nCount[-321]==1)||
 	  (nCount[-211]==1&&nCount[ 321]==1)))
-	 _nMeson[1]->fill(event.weight());
+	 _nMeson[1]->fill();
       else if(ntotal==3 && nCount[321]==1 &&
 	      nCount[-321]==1 && nCount[111]==1)
-	 _nMeson[2]->fill(event.weight());
+	 _nMeson[2]->fill();
     }
 
 
     /// Normalise histograms etc., after the run
     void finalize() {
       for(unsigned int ix=1;ix<6;++ix) {
 	double sigma = _nMeson[ix]->val();
 	double error = _nMeson[ix]->err();
     	sigma *= crossSection()/ sumOfWeights() /nanobarn;
     	error *= crossSection()/ sumOfWeights() /nanobarn; 
 	Scatter2D temphisto(refData(ix, 1, 1));
-    	Scatter2DPtr  mult = bookScatter2D(ix, 1, 1);
+    	Scatter2DPtr  mult;
+        book(mult, ix, 1, 1);
 	for (size_t b = 0; b < temphisto.numPoints(); b++) {
 	  const double x  = temphisto.point(b).x();
 	  pair<double,double> ex = temphisto.point(b).xErrs();
 	  pair<double,double> ex2 = ex;
 	  if(ex2.first ==0.) ex2. first=0.0001;
 	  if(ex2.second==0.) ex2.second=0.0001;
 	  if (inRange(sqrtS()/GeV, x-ex2.first, x+ex2.second)) {
 	    mult->addPoint(x, sigma, ex, make_pair(error,error));
 	  }
 	  else {
 	    mult->addPoint(x, 0., ex, make_pair(0.,.0));
 	  }
 	}
       }
     }
 
     //@}
 
 
     /// @name Histograms
     //@{
     CounterPtr _nMeson[6];
     //@}
 
 
   };
 
 
   // The hook for the plugin system
   DECLARE_RIVET_PLUGIN(BABAR_2008_I765258);
 
 
 }
diff --git a/analyses/pluginBABAR/BABAR_2008_I776519.cc b/analyses/pluginBABAR/BABAR_2008_I776519.cc
--- a/analyses/pluginBABAR/BABAR_2008_I776519.cc
+++ b/analyses/pluginBABAR/BABAR_2008_I776519.cc
@@ -1,139 +1,140 @@
 // -*- C++ -*-
 #include "Rivet/Analysis.hh"
 #include "Rivet/Projections/FinalState.hh"
 #include "Rivet/Projections/UnstableParticles.hh"
 
 namespace Rivet {
 
 
   /// @brief Add a short analysis description here
   class BABAR_2008_I776519 : public Analysis {
   public:
 
     /// Constructor
     DEFAULT_RIVET_ANALYSIS_CTOR(BABAR_2008_I776519);
 
 
     /// @name Analysis methods
     //@{
 
     /// Book histograms and initialise projections before the run
     void init() {
 
       // Initialise and register projections
       declare(FinalState(), "FS");
       declare(UnstableParticles(), "UFS");
-      _nD0 = bookCounter("/TMP/nD0");
-      _nDp = bookCounter("/TMP/nDp");
+      book(_nD0, "/TMP/nD0");
+      book(_nDp, "/TMP/nDp");
 
     }
 
     void findChildren(const Particle & p,map<long,int> & nRes, int &ncount) {
-      foreach(const Particle &child, p.children()) {
+      for (const Particle &child : p.children()) {
 	if(child.children().empty()) {
-	  nRes[child.pdgId()]-=1;
+	  nRes[child.pid()]-=1;
 	  --ncount;
 	}
 	else
 	  findChildren(child,nRes,ncount);
       }
     }
 
     /// Perform the per-event analysis
     void analyze(const Event& event) {
 
       const FinalState& fs = apply<FinalState>(event, "FS");
 
       map<long,int> nCount;
       int ntotal(0);
-      foreach (const Particle& p, fs.particles()) {
-	nCount[p.pdgId()] += 1;
+      for (const Particle& p : fs.particles()) {
+	nCount[p.pid()] += 1;
 	++ntotal;
       }
       const FinalState& ufs = apply<FinalState>(event, "UFS");
 
       for(unsigned int ix=0;ix<ufs.particles().size();++ix) {
 	const Particle& p1 = ufs.particles()[ix];
-	if(abs(p1.pdgId())!=411 && abs(p1.pdgId())!=421)
+	if(abs(p1.pid())!=411 && abs(p1.pid())!=421)
 	  continue;
 	map<long,int> nRes = nCount;
 	int ncount = ntotal;
 	findChildren(p1,nRes,ncount);
 	bool matched=false;
 	for(unsigned int iy=0;iy<ufs.particles().size();++iy) {
 	  if(ix==iy) continue;
 	  const Particle& p2 = ufs.particles()[iy];
-	  if(p2.pdgId()!=-p1.pdgId()) continue;
+	  if(p2.pid()!=-p1.pid()) continue;
 	  map<long,int> nRes2 = nRes;
 	  int ncount2 = ncount;
 	  findChildren(p2,nRes2,ncount2);
 	  if(ncount2!=0) continue;
 	  matched=true;
 	  for(auto const & val : nRes2) {
 	    if(val.second!=0) {
 	      matched = false;
 	      break;
 	    }
 	  }
 	  if(matched) break;
 	}
 	if(matched) {
-	  if(abs(p1.pdgId())==411)
-	    _nDp->fill(event.weight());
-	  else if(abs(p1.pdgId())==421)
-	    _nD0->fill(event.weight());
+	  if(abs(p1.pid())==411)
+	    _nDp->fill();
+	  else if(abs(p1.pid())==421)
+	    _nD0->fill();
 	}
       }
     }
 
 
     /// Normalise histograms etc., after the run
     void finalize() {
 
       for(unsigned int ix=1;ix<3;++ix) {
 	double sigma,error;
 	if(ix==1) {
 	  sigma = _nD0->val();
 	  error = _nD0->err();
 	}
 	else {
 	  sigma = _nDp->val();
 	  error = _nDp->err();
 	}
     	sigma *= crossSection()/ sumOfWeights() /nanobarn;
     	error *= crossSection()/ sumOfWeights() /nanobarn; 
 	Scatter2D temphisto(refData(1, 1, ix));
-    	Scatter2DPtr  mult = bookScatter2D(1, 1, ix);
+    	Scatter2DPtr  mult;
+        book(mult, 1, 1, ix);
 	for (size_t b = 0; b < temphisto.numPoints(); b++) {
 	  const double x  = temphisto.point(b).x();
 	  pair<double,double> ex = temphisto.point(b).xErrs();
 	  pair<double,double> ex2 = ex;
 	  if(ex2.first ==0.) ex2. first=0.0001;
 	  if(ex2.second==0.) ex2.second=0.0001;
 	  if (inRange(sqrtS()/GeV, x-ex2.first, x+ex2.second)) {
 	    mult->addPoint(x, sigma, ex, make_pair(error,error));
 	  }
 	  else {
 	    mult->addPoint(x, 0., ex, make_pair(0.,.0));
 	  }
 	}
       }
     }
 
     //@}
 
 
     /// @name Histograms
     //@{
     CounterPtr _nD0,_nDp;
     //@}
 
 
   };
 
 
   // The hook for the plugin system
   DECLARE_RIVET_PLUGIN(BABAR_2008_I776519);
 
 
 }
diff --git a/analyses/pluginBABAR/BABAR_2009_I797507.cc b/analyses/pluginBABAR/BABAR_2009_I797507.cc
--- a/analyses/pluginBABAR/BABAR_2009_I797507.cc
+++ b/analyses/pluginBABAR/BABAR_2009_I797507.cc
@@ -1,111 +1,114 @@
 // -*- C++ -*-
 #include "Rivet/Analysis.hh"
 #include "Rivet/Projections/FinalState.hh"
 #include "Rivet/Projections/UnstableParticles.hh"
 
 namespace Rivet {
 
 
   /// @brief Add a short analysis description here
   class BABAR_2009_I797507 : public Analysis {
   public:
 
     /// Constructor
     DEFAULT_RIVET_ANALYSIS_CTOR(BABAR_2009_I797507);
 
 
     /// @name Analysis methods
     //@{
 
     /// Book histograms and initialise projections before the run
     void init() {
 
       // Initialise and register projections
       declare(FinalState(), "FS");
       declare(UnstableParticles(), "UFS");
 
       // Book histograms
-      _c_hadrons = bookCounter("/TMP/sigma_hadrons");
-      _c_muons   = bookCounter("/TMP/sigma_muons");
+      book(_c_hadrons, "/TMP/sigma_hadrons");
+      book(_c_muons  , "/TMP/sigma_muons");
     }
 
 
     /// Perform the per-event analysis
     void analyze(const Event& event) {
       const FinalState& fs = apply<FinalState>(event, "FS");
       map<long,int> nCount;
       int ntotal(0);
-      foreach (const Particle& p, fs.particles()) {
-	nCount[p.pdgId()] += 1;
+      for (const Particle& p : fs.particles()) {
+	nCount[p.pid()] += 1;
 	++ntotal;
       }
       bool isBottom(false);
       const UnstableParticles& ufs = apply<UnstableParticles>(event, "UFS");
-      foreach (const Particle& p, ufs.particles()) {
-        if (PID::isBottomHadron(p.pdgId())) {
+      for (const Particle& p : ufs.particles()) {
+        if (PID::isBottomHadron(p.pid())) {
 	  isBottom = true;
 	  break;
 	}
       }
       
       // mu+mu- + photons
       if(nCount[-13]==1 and nCount[13]==1 &&
 	 ntotal==2+nCount[22])
-	_c_muons->fill(event.weight());
+	_c_muons->fill();
       // everything else
       else if(isBottom) {
-	_c_hadrons->fill(event.weight());
+	_c_hadrons->fill();
       }
     }
 
 
     /// Normalise histograms etc., after the run
     void finalize() {
       Scatter1D R = *_c_hadrons/ *_c_muons;
       double              rval = R.point(0).x();
       pair<double,double> rerr = R.point(0).xErrs();
       double fact = crossSection()/ sumOfWeights() /picobarn;
       double sig_h = _c_hadrons->val()*fact;
       double err_h = _c_hadrons->err()*fact;
       double sig_m = _c_muons  ->val()*fact;
       double err_m = _c_muons  ->err()*fact;
       Scatter2D temphisto(refData(1, 1, 1));
-      Scatter2DPtr hadrons  = bookScatter2D("sigma_hadrons");
-      Scatter2DPtr muons    = bookScatter2D("sigma_muons"  );
-      Scatter2DPtr     mult = bookScatter2D(1, 1, 1);
+      Scatter2DPtr hadrons;
+      book(hadrons, "sigma_hadrons");
+      Scatter2DPtr muons;
+      book(muons, "sigma_muons"  );
+      Scatter2DPtr     mult;
+      book(mult, 1, 1, 1);
       for (size_t b = 0; b < temphisto.numPoints(); b++) {
 	const double x  = temphisto.point(b).x();
 	pair<double,double> ex = temphisto.point(b).xErrs();
 	pair<double,double> ex2 = ex;
 	if(ex2.first ==0.) ex2. first=0.0001;
 	if(ex2.second==0.) ex2.second=0.0001;
 	if (inRange(sqrtS()/GeV, x-ex2.first, x+ex2.second)) {
 	  mult   ->addPoint(x, rval, ex, rerr);
 	  hadrons->addPoint(x, sig_h, ex, make_pair(err_h,err_h));
 	  muons  ->addPoint(x, sig_m, ex, make_pair(err_m,err_m));
 	}
 	else {
 	  mult   ->addPoint(x, 0., ex, make_pair(0.,.0));
 	  hadrons->addPoint(x, 0., ex, make_pair(0.,.0));
 	  muons  ->addPoint(x, 0., ex, make_pair(0.,.0));
 	}
       }
     }
 
     //@}
 
 
     /// @name Histograms
     //@{
     CounterPtr _c_hadrons, _c_muons;
     //@}
 
 
   };
 
 
   // The hook for the plugin system
   DECLARE_RIVET_PLUGIN(BABAR_2009_I797507);
 
 
 }
diff --git a/analyses/pluginBABAR/BABAR_2009_I829441.cc b/analyses/pluginBABAR/BABAR_2009_I829441.cc
--- a/analyses/pluginBABAR/BABAR_2009_I829441.cc
+++ b/analyses/pluginBABAR/BABAR_2009_I829441.cc
@@ -1,80 +1,81 @@
 // -*- C++ -*-
 #include "Rivet/Analysis.hh"
 #include "Rivet/Projections/FinalState.hh"
 
 namespace Rivet {
 
 
   /// @brief Add a short analysis description here
   class BABAR_2009_I829441 : public Analysis {
   public:
 
     /// Constructor
     DEFAULT_RIVET_ANALYSIS_CTOR(BABAR_2009_I829441);
 
 
     /// @name Analysis methods
     //@{
 
     /// Book histograms and initialise projections before the run
     void init() {
       // Initialise and register projections
       declare(FinalState(), "FS");
 
       // Book histograms
-      _npion = bookCounter("TMP/pion");
+      book(_npion, "TMP/pion");
     }
 
 
     /// Perform the per-event analysis
     void analyze(const Event& event) {
       const FinalState& fs = apply<FinalState>(event, "FS");
       if(fs.particles().size()!=2) vetoEvent;
-      foreach (const Particle& p, fs.particles()) {
-	if(abs(p.pdgId())!=PID::PIPLUS) vetoEvent;
+      for (const Particle& p : fs.particles()) {
+	if(abs(p.pid())!=PID::PIPLUS) vetoEvent;
       }
-      _npion->fill(event.weight());
+      _npion->fill();
     }
 
 
     /// Normalise histograms etc., after the run
     void finalize() {
       double sigma = _npion->val();
       double error = _npion->err();
       sigma *= crossSection()/ sumOfWeights() /nanobarn;
       error *= crossSection()/ sumOfWeights() /nanobarn;
       Scatter2D temphisto(refData(1, 1, 1));
-      Scatter2DPtr  mult = bookScatter2D(1, 1, 1);
+      Scatter2DPtr  mult;
+      book(mult, 1, 1, 1);
       for (size_t b = 0; b < temphisto.numPoints(); b++) {
 	const double x  = temphisto.point(b).x();
 	pair<double,double> ex = temphisto.point(b).xErrs();
 	pair<double,double> ex2 = ex;
 	if(ex2.first ==0.) ex2. first=0.0001;
 	if(ex2.second==0.) ex2.second=0.0001;
 	if (inRange(sqrtS()/GeV, x-ex2.first, x+ex2.second)) {
 	  mult->addPoint(x, sigma, ex, make_pair(error,error));
 	}
 	else {
 	  mult->addPoint(x, 0., ex, make_pair(0.,.0));
 	}
       }
 
     }
 
     //@}
 
 
     /// @name Histograms
     //@{
     CounterPtr _npion;
     //@}
 
 
   };
 
 
   // The hook for the plugin system
   DECLARE_RIVET_PLUGIN(BABAR_2009_I829441);
 
 
 }
diff --git a/analyses/pluginBABAR/BABAR_2012_I1086164.cc b/analyses/pluginBABAR/BABAR_2012_I1086164.cc
--- a/analyses/pluginBABAR/BABAR_2012_I1086164.cc
+++ b/analyses/pluginBABAR/BABAR_2012_I1086164.cc
@@ -1,82 +1,83 @@
 // -*- C++ -*-
 #include "Rivet/Analysis.hh"
 #include "Rivet/Projections/FinalState.hh"
 
 
 namespace Rivet {
 
 
   /// @brief Add a short analysis description here
   class BABAR_2012_I1086164 : public Analysis {
   public:
 
     /// Constructor
     DEFAULT_RIVET_ANALYSIS_CTOR(BABAR_2012_I1086164);
 
 
     /// @name Analysis methods
     //@{
 
     /// Book histograms and initialise projections before the run
     void init() {
 
       // Initialise and register projections
       declare(FinalState(), "FS");
 
       // Book histograms
-      _npion = bookCounter("TMP/pion");
+      book(_npion, "TMP/pion");
 
     }
 
 
     /// Perform the per-event analysis
     void analyze(const Event& event) {
       const FinalState& fs = apply<FinalState>(event, "FS");
       if(fs.particles().size()!=4) vetoEvent;
-      foreach (const Particle& p, fs.particles()) {
-	if(abs(p.pdgId())!=PID::PIPLUS) vetoEvent;
+      for (const Particle& p : fs.particles()) {
+	if(abs(p.pid())!=PID::PIPLUS) vetoEvent;
       }
-      _npion->fill(event.weight());
+      _npion->fill();
     }
 
 
     /// Normalise histograms etc., after the run
     void finalize() {
       double sigma = _npion->val();
       double error = _npion->err();
       sigma *= crossSection()/ sumOfWeights() /nanobarn;
       error *= crossSection()/ sumOfWeights() /nanobarn;
       Scatter2D temphisto(refData(1, 1, 1));
-      Scatter2DPtr  mult = bookScatter2D(1, 1, 1);
+      Scatter2DPtr  mult;
+      book(mult, 1, 1, 1);
       for (size_t b = 0; b < temphisto.numPoints(); b++) {
 	const double x  = temphisto.point(b).x();
 	pair<double,double> ex = temphisto.point(b).xErrs();
 	pair<double,double> ex2 = ex;
 	if(ex2.first ==0.) ex2. first=0.0001;
 	if(ex2.second==0.) ex2.second=0.0001;
 	if (inRange(sqrtS()/MeV, x-ex2.first, x+ex2.second)) {
 	  mult->addPoint(x, sigma, ex, make_pair(error,error));
 	}
 	else {
 	  mult->addPoint(x, 0., ex, make_pair(0.,.0));
 	}
       }
     }
 
     //@}
 
 
     /// @name Histograms
     //@{
     CounterPtr _npion;
     //@}
 
 
   };
 
 
   // The hook for the plugin system
   DECLARE_RIVET_PLUGIN(BABAR_2012_I1086164);
 
 
 }
diff --git a/analyses/pluginBABAR/BABAR_2012_I892684.cc b/analyses/pluginBABAR/BABAR_2012_I892684.cc
--- a/analyses/pluginBABAR/BABAR_2012_I892684.cc
+++ b/analyses/pluginBABAR/BABAR_2012_I892684.cc
@@ -1,219 +1,220 @@
 // -*- C++ -*-
 #include "Rivet/Analysis.hh"
 #include "Rivet/Projections/FinalState.hh"
 #include "Rivet/Projections/UnstableParticles.hh"
 
 
 namespace Rivet {
 
 
   /// @brief Add a short analysis description here
   class BABAR_2012_I892684 : public Analysis {
   public:
 
     /// Constructor
     DEFAULT_RIVET_ANALYSIS_CTOR(BABAR_2012_I892684);
 
 
     /// @name Analysis methods
     //@{
 
     /// Book histograms and initialise projections before the run
     void init() {
 
       // Initialise and register projections
       declare(FinalState(), "FS");
       declare(UnstableParticles(), "UFS");
 
-      _cKpKmpippim  = bookCounter("TMP/KpKmpippim");
-      _cKstarKpi    = bookCounter("TMP/KstarKpi");
-      _cphipippim   = bookCounter("TMP/phipippim");
-      _cphif0_980   = bookCounter("TMP/phif0_980");
-      _cphif0_600   = bookCounter("TMP/phif0_600");
-      _cKpKmpi0pi0  = bookCounter("TMP/KpKmpi0pi0");
-      _cphif0pi0pi0 = bookCounter("TMP/phif0pi0pi0");
-      _c2Kp2Km      = bookCounter("TMP/2Kp2Km");
+      book(_cKpKmpippim , "TMP/KpKmpippim");
+      book(_cKstarKpi   , "TMP/KstarKpi");
+      book(_cphipippim  , "TMP/phipippim");
+      book(_cphif0_980  , "TMP/phif0_980");
+      book(_cphif0_600  , "TMP/phif0_600");
+      book(_cKpKmpi0pi0 , "TMP/KpKmpi0pi0");
+      book(_cphif0pi0pi0, "TMP/phif0pi0pi0");
+      book(_c2Kp2Km     , "TMP/2Kp2Km");
     }
 
     void findChildren(const Particle & p,map<long,int> & nRes, int &ncount) {
-      foreach(const Particle &child, p.children()) {
+      for (const Particle &child : p.children()) {
 	if(child.children().empty()) {
-	  nRes[child.pdgId()]-=1;
+	  nRes[child.pid()]-=1;
 	  --ncount;
 	}
 	else
 	  findChildren(child,nRes,ncount);
       }
     }
 
 
     /// Perform the per-event analysis
     void analyze(const Event& event) {
       const FinalState& fs = apply<FinalState>(event, "FS");
 
       map<long,int> nCount;
       int ntotal(0);
-      foreach (const Particle& p, fs.particles()) {
-	nCount[p.pdgId()] += 1;
+      for (const Particle& p : fs.particles()) {
+	nCount[p.pid()] += 1;
 	++ntotal;
       }
       const FinalState& ufs = apply<FinalState>(event, "UFS");
-      foreach (const Particle& p, ufs.particles()) {
+      for (const Particle& p : ufs.particles()) {
 	if(p.children().empty()) continue;
 	// K*0
-	if(abs(p.pdgId())==313) {
+	if(abs(p.pid())==313) {
 	  map<long,int> nRes=nCount;
 	  int ncount = ntotal;
 	  findChildren(p,nRes,ncount);
 	  // K* K+/- pi-/+
 	  if(ncount !=2 ) continue;
 	  bool matched = true;
 	  for(auto const & val : nRes) {
 	    if(abs(val.first)==321 || abs(val.first)==211) {
 	      continue;
 	    }
 	    else if(val.second!=0) {
 	      matched = false;
 	      break;
 	    }
 	  }
 	  if(matched==false) continue;
 	  if((nCount[321] == 1 && nCount[-321] ==0 &&
 	      nCount[211] == 0 && nCount[-211] == 1) ||
 	     (nCount[321] == 0 && nCount[-321] ==1 &&
 	      nCount[211] == 1 && nCount[-211] == 0))
-	    _cKstarKpi->fill(event.weight());
+	    _cKstarKpi->fill();
 	}
-	else if(p.pdgId()==333) {
+	else if(p.pid()==333) {
 	  map<long,int> nRes=nCount;
 	  int ncount = ntotal;
 	  findChildren(p,nRes,ncount);
 	  // phi pi+pi-
 	  if(ncount==2) {
 	    bool matched = true;
 	    for(auto const & val : nRes) {
 	      if(abs(val.first)==211) {
 		if(val.second!=1) {
 		  matched = false;
 		  break;
 		}
 	      }
 	      else if(val.second!=0) {
 		matched = false;
 		break;
 	      }
 	    }
 	    if(matched)
-	      _cphipippim->fill(event.weight());
+	      _cphipippim->fill();
 	  }
-	  foreach (const Particle& p2, ufs.particles()) {
-	    if(p2.pdgId()!=9010221&&p2.pdgId()!=9000221) continue;
+	  for (const Particle& p2 : ufs.particles()) {
+	    if(p2.pid()!=9010221&&p2.pid()!=9000221) continue;
 	    if(p2.parents()[0].isSame(p)) continue;
 	    map<long,int> nResB = nRes;
 	    int ncountB = ncount;
 	    findChildren(p2,nResB,ncountB);
 	    if(ncountB!=0) continue;
 	    bool matched2 = true;
 	    for(auto const & val : nResB) {
 	      if(val.second!=0) {
 		matched2 = false;
 		break;
 	      }
 	    }
 	    if(matched2) {
-	      if(p2.pdgId()==9010221) {
-		_cphif0pi0pi0->fill(event.weight());
-		_cphif0_980  ->fill(event.weight());
+	      if(p2.pid()==9010221) {
+		_cphif0pi0pi0->fill();
+		_cphif0_980  ->fill();
 	      }
 	      else {
-		_cphif0_600  ->fill(event.weight());
+		_cphif0_600  ->fill();
 	      }
 	    }
 	  }
 	}
       }
       if(ntotal==4) {
 	if(nCount[321]==1 && nCount[-321]==1 && nCount[211]==1 && nCount[-211]==1)
-	  _cKpKmpippim->fill(event.weight());
+	  _cKpKmpippim->fill();
 	else if( nCount[321]==1 && nCount[-321]==1 && nCount[111]==2)
-	  _cKpKmpi0pi0->fill(event.weight());
+	  _cKpKmpi0pi0->fill();
 	else if( nCount[321]==2 && nCount[-321]==2)
-	  _c2Kp2Km->fill(event.weight());
+	  _c2Kp2Km->fill();
       }
     }
 
 
     /// Normalise histograms etc., after the run
     void finalize() {
       for(unsigned int ix=1;ix<9;++ix) {
 	double sigma = 0., error = 0.;
 	if(ix==1) {
 	  sigma = _cKpKmpippim->val();
 	  error = _cKpKmpippim->err();
 	}
 	else if(ix==2) {
 	  sigma = _cKstarKpi->val();
 	  error = _cKstarKpi->err();
 	}
      	else if(ix==3) {
 	  sigma = _cphipippim->val();
 	  error = _cphipippim->err();
 	}
      	else if(ix==4) {
 	  sigma = _cphif0_980->val();
 	  error = _cphif0_980->err();
 	}
      	else if(ix==5) {
 	  sigma = _cphif0_600->val();
 	  error = _cphif0_600->err();
 	}
      	else if(ix==6) {
 	  sigma = _cKpKmpi0pi0->val();
 	  error = _cKpKmpi0pi0->err();
 	}
      	else if(ix==7) {
 	  sigma = _cphif0pi0pi0->val();
 	  error = _cphif0pi0pi0->err();
 	}
      	else if(ix==8) {
 	  sigma =  _c2Kp2Km->val();
 	  error =  _c2Kp2Km->err();
 	}
     	sigma *= crossSection()/ sumOfWeights() /nanobarn;
     	error *= crossSection()/ sumOfWeights() /nanobarn;
 	Scatter2D temphisto(refData(ix, 1, 1));
-	Scatter2DPtr  mult = bookScatter2D(ix, 1, 1);
+	Scatter2DPtr  mult;
+        book(mult, ix, 1, 1);
 	for (size_t b = 0; b < temphisto.numPoints(); b++) {
 	  const double x  = temphisto.point(b).x();
 	  pair<double,double> ex = temphisto.point(b).xErrs();
 	  pair<double,double> ex2 = ex;
 	  if(ex2.first ==0.) ex2. first=0.0001;
 	  if(ex2.second==0.) ex2.second=0.0001;
 	  if (inRange(sqrtS()/GeV, x-ex2.first, x+ex2.second)) {
 	    mult->addPoint(x, sigma, ex, make_pair(error,error));
 	  }
 	  else {
 	    mult->addPoint(x, 0., ex, make_pair(0.,.0));
 	  }
 	}
       }
     }
 
     //@}
 
 
     /// @name Histograms
     //@{
     CounterPtr _cKpKmpippim, _cKstarKpi, _cphipippim,
       _cphif0_980,_cphif0_600, _cKpKmpi0pi0, _cphif0pi0pi0, _c2Kp2Km;
     //@}
 
 
   };
 
 
   // The hook for the plugin system
   DECLARE_RIVET_PLUGIN(BABAR_2012_I892684);
 
 
 }
diff --git a/analyses/pluginBABAR/BABAR_2013_I1217421.cc b/analyses/pluginBABAR/BABAR_2013_I1217421.cc
--- a/analyses/pluginBABAR/BABAR_2013_I1217421.cc
+++ b/analyses/pluginBABAR/BABAR_2013_I1217421.cc
@@ -1,81 +1,82 @@
 // -*- C++ -*-
 #include "Rivet/Analysis.hh"
 #include "Rivet/Projections/FinalState.hh"
 
 
 namespace Rivet {
 
 
   /// @brief Add a short analysis description here
   class BABAR_2013_I1217421 : public Analysis {
   public:
 
     /// Constructor
     DEFAULT_RIVET_ANALYSIS_CTOR(BABAR_2013_I1217421);
 
 
     /// @name Analysis methods
     //@{
 
     /// Book histograms and initialise projections before the run
     void init() {
 
       // Initialise and register projections
       declare(FinalState(), "FS");
 
       // Book histograms
-      _nproton = bookCounter("TMP/proton");
+      book(_nproton, "TMP/proton");
     }
 
 
     /// Perform the per-event analysis
     void analyze(const Event& event) {
       const FinalState& fs = apply<FinalState>(event, "FS");
       if(fs.particles().size()!=2) vetoEvent;
-      foreach (const Particle& p, fs.particles()) {
-	if(abs(p.pdgId())!=PID::PROTON) vetoEvent;
+      for (const Particle& p : fs.particles()) {
+	if(abs(p.pid())!=PID::PROTON) vetoEvent;
       }
-      _nproton->fill(event.weight());
+      _nproton->fill();
     }
 
 
     /// Normalise histograms etc., after the run
     void finalize() {
       double sigma = _nproton->val();
       double error = _nproton->err();
       sigma *= crossSection()/ sumOfWeights() /picobarn;
       error *= crossSection()/ sumOfWeights() /picobarn;
       Scatter2D temphisto(refData(1, 1, 1));
-      Scatter2DPtr  mult = bookScatter2D(1, 1, 1);
+      Scatter2DPtr  mult;
+      book(mult, 1, 1, 1);
       for (size_t b = 0; b < temphisto.numPoints(); b++) {
 	const double x  = temphisto.point(b).x();
 	pair<double,double> ex = temphisto.point(b).xErrs();
 	pair<double,double> ex2 = ex;
 	if(ex2.first ==0.) ex2. first=0.0001;
 	if(ex2.second==0.) ex2.second=0.0001;
 	if (inRange(sqrtS()/GeV, x-ex2.first, x+ex2.second)) {
 	  mult->addPoint(x, sigma, ex, make_pair(error,error));
 	}
 	else {
 	  mult->addPoint(x, 0., ex, make_pair(0.,.0));
 	}
       }
     }
 
     //@}
 
 
     /// @name Histograms
     //@{
     CounterPtr _nproton;
     //@}
 
 
   };
 
 
   // The hook for the plugin system
   DECLARE_RIVET_PLUGIN(BABAR_2013_I1217421);
 
 
 }
diff --git a/analyses/pluginBABAR/BABAR_2013_I1238807.cc b/analyses/pluginBABAR/BABAR_2013_I1238807.cc
--- a/analyses/pluginBABAR/BABAR_2013_I1238807.cc
+++ b/analyses/pluginBABAR/BABAR_2013_I1238807.cc
@@ -1,84 +1,85 @@
 // -*- C++ -*-
 #include "Rivet/Analysis.hh"
 #include "Rivet/Projections/FinalState.hh"
 
 
 namespace Rivet {
 
 
   /// @brief Add a short analysis description here
   class BABAR_2013_I1238807 : public Analysis {
   public:
 
     /// Constructor
     DEFAULT_RIVET_ANALYSIS_CTOR(BABAR_2013_I1238807);
 
 
     /// @name Analysis methods
     //@{
 
     /// Book histograms and initialise projections before the run
     void init() {
 
       // Initialise and register projections
       declare(FinalState(), "FS");
 
       // Book histograms
-      _nkaon = bookCounter("TMP/kaon");
+      book(_nkaon, "TMP/kaon");
 
     }
 
 
     /// Perform the per-event analysis
     void analyze(const Event& event) {
       const FinalState& fs = apply<FinalState>(event, "FS");
       if(fs.particles().size()!=2) vetoEvent;
-      foreach (const Particle& p, fs.particles()) {
-	if(abs(p.pdgId())!=PID::KPLUS) vetoEvent;
+      for (const Particle& p : fs.particles()) {
+	if(abs(p.pid())!=PID::KPLUS) vetoEvent;
       }
-      _nkaon->fill(event.weight());
+      _nkaon->fill();
 
     }
 
 
     /// Normalise histograms etc., after the run
     void finalize() {
       double sigma = _nkaon->val();
       double error = _nkaon->err();
       sigma *= crossSection()/ sumOfWeights() /nanobarn;
       error *= crossSection()/ sumOfWeights() /nanobarn;
 	Scatter2D temphisto(refData(1, 1, 1));
-	Scatter2DPtr  mult = bookScatter2D(1, 1, 1);
+	Scatter2DPtr  mult;
+        book(mult, 1, 1, 1);
 	for (size_t b = 0; b < temphisto.numPoints(); b++) {
 	  const double x  = temphisto.point(b).x();
 	  pair<double,double> ex = temphisto.point(b).xErrs();
 	  pair<double,double> ex2 = ex;
 	  if(ex2.first ==0.) ex2. first=0.0001;
 	  if(ex2.second==0.) ex2.second=0.0001;
 	  if (inRange(sqrtS()/GeV, x-ex2.first, x+ex2.second)) {
 	    mult->addPoint(x, sigma, ex, make_pair(error,error));
 	  }
 	  else {
 	    mult->addPoint(x, 0., ex, make_pair(0.,.0));
 	  }
 	} 
 
     }
 
     //@}
 
 
     /// @name Histograms
     //@{
     CounterPtr _nkaon;
     //@}
 
 
   };
 
 
   // The hook for the plugin system
   DECLARE_RIVET_PLUGIN(BABAR_2013_I1238807);
 
 
 }
diff --git a/analyses/pluginBABAR/BABAR_2014_I1287920.cc b/analyses/pluginBABAR/BABAR_2014_I1287920.cc
--- a/analyses/pluginBABAR/BABAR_2014_I1287920.cc
+++ b/analyses/pluginBABAR/BABAR_2014_I1287920.cc
@@ -1,114 +1,115 @@
 // -*- C++ -*-
 #include "Rivet/Analysis.hh"
 #include "Rivet/Projections/FinalState.hh"
 
 
 namespace Rivet {
 
 
   /// @brief Add a short analysis description here
   class BABAR_2014_I1287920 : public Analysis {
   public:
 
     /// Constructor
     DEFAULT_RIVET_ANALYSIS_CTOR(BABAR_2014_I1287920);
 
 
     /// @name Analysis methods
     //@{
 
     /// Book histograms and initialise projections before the run
     void init() {
 
       // Initialise and register projections
       declare(FinalState(), "FS");
 
       // Book histograms
-      _nKSKL     = bookCounter("TMP/nKSKL");
-      _nKSKLpipi = bookCounter("TMP/nKSKLpipi");
-      _nKSKSpipi = bookCounter("TMP/nKSKSpipi");
-      _nKSKSKpKm = bookCounter("TMP/nKSKSKpKm");
+      book(_nKSKL    , "TMP/nKSKL");
+      book(_nKSKLpipi, "TMP/nKSKLpipi");
+      book(_nKSKSpipi, "TMP/nKSKSpipi");
+      book(_nKSKSKpKm, "TMP/nKSKSKpKm");
     }
 
 
     /// Perform the per-event analysis
     void analyze(const Event& event) {
       const FinalState& fs = apply<FinalState>(event, "FS");
 
       map<long,int> nCount;
       int ntotal(0);
-      foreach (const Particle& p, fs.particles()) {
-	nCount[p.pdgId()] += 1;
+      for (const Particle& p : fs.particles()) {
+	nCount[p.pid()] += 1;
 	++ntotal;
       }
       
       if(ntotal==2 && nCount[130]==1 && nCount[310]==1)
-	_nKSKL->fill(event.weight());
+	_nKSKL->fill();
       else if( ntotal==4 &&  nCount[130]==1 && nCount[310]==1 && nCount[211]==1 && nCount[-211]==1)
-	_nKSKLpipi->fill(event.weight());
+	_nKSKLpipi->fill();
       else if( ntotal==4 && nCount[310]==2 && nCount[211]==1 && nCount[-211]==1 )
-	_nKSKSpipi->fill(event.weight());
+	_nKSKSpipi->fill();
       else if( ntotal==4 && nCount[310]==2 && nCount[321]==1 && nCount[-321]==1)
-	_nKSKSKpKm->fill(event.weight());
+	_nKSKSKpKm->fill();
 
     }
 
 
     /// Normalise histograms etc., after the run
     void finalize() {
 
       for(unsigned int ix=9;ix<13;++ix) {
 	double sigma = 0., error = 0.;
 	if(ix==9) {
 	  sigma =  _nKSKL->val();
 	  error =  _nKSKL->err();
 	}
 	else if(ix==10) {
 	  sigma = _nKSKLpipi->val();
 	  error = _nKSKLpipi->err();
 	}
      	else if(ix==11) {
 	  sigma = _nKSKSpipi->val();
 	  error = _nKSKSpipi->err();
 	}
      	else if(ix==12) {
 	  sigma = _nKSKSKpKm->val();
 	  error = _nKSKSKpKm->err();
 	}
     	sigma *= crossSection()/ sumOfWeights() /nanobarn;
     	error *= crossSection()/ sumOfWeights() /nanobarn;
 	Scatter2D temphisto(refData(ix, 1, 1));
-	Scatter2DPtr  mult = bookScatter2D(ix, 1, 1);
+	Scatter2DPtr  mult;
+        book(mult, ix, 1, 1);
 	for (size_t b = 0; b < temphisto.numPoints(); b++) {
 	  const double x  = temphisto.point(b).x();
 	  pair<double,double> ex = temphisto.point(b).xErrs();
 	  pair<double,double> ex2 = ex;
 	  if(ex2.first ==0.) ex2. first=0.0001;
 	  if(ex2.second==0.) ex2.second=0.0001;
 	  if (inRange(sqrtS()/GeV, x-ex2.first, x+ex2.second)) {
 	    mult->addPoint(x, sigma, ex, make_pair(error,error));
 	  }
 	  else {
 	    mult->addPoint(x, 0., ex, make_pair(0.,.0));
 	  }
 	}
       }
     }
 
     //@}
 
 
     /// @name Histograms
     //@{
     CounterPtr _nKSKL,_nKSKLpipi,_nKSKSpipi,_nKSKSKpKm;
     //@}
 
 
   };
 
 
   // The hook for the plugin system
   DECLARE_RIVET_PLUGIN(BABAR_2014_I1287920);
 
 
 }
diff --git a/analyses/pluginBABAR/BABAR_2015_I1383130.cc b/analyses/pluginBABAR/BABAR_2015_I1383130.cc
--- a/analyses/pluginBABAR/BABAR_2015_I1383130.cc
+++ b/analyses/pluginBABAR/BABAR_2015_I1383130.cc
@@ -1,81 +1,82 @@
 // -*- C++ -*-
 #include "Rivet/Analysis.hh"
 #include "Rivet/Projections/FinalState.hh"
 
 
 namespace Rivet {
 
 
   /// @brief Add a short analysis description here
   class BABAR_2015_I1383130 : public Analysis {
   public:
 
     /// Constructor
     DEFAULT_RIVET_ANALYSIS_CTOR(BABAR_2015_I1383130);
 
 
     /// @name Analysis methods
     //@{
 
     /// Book histograms and initialise projections before the run
     void init() {
 
       // Initialise and register projections
       declare(FinalState(), "FS");
 
       // Book histograms
-      _nkaon = bookCounter("TMP/kaon");
+      book(_nkaon, "TMP/kaon");
 
     }
 
     /// Perform the per-event analysis
     void analyze(const Event& event) {
       const FinalState& fs = apply<FinalState>(event, "FS");
       if(fs.particles().size()!=2) vetoEvent;
-      foreach (const Particle& p, fs.particles()) {
-	if(abs(p.pdgId())!=PID::KPLUS) vetoEvent;
+      for (const Particle& p : fs.particles()) {
+	if(abs(p.pid())!=PID::KPLUS) vetoEvent;
       }
-      _nkaon->fill(event.weight());
+      _nkaon->fill();
     }
 
 
     /// Normalise histograms etc., after the run
     void finalize() {
       double sigma = _nkaon->val();
       double error = _nkaon->err();
       sigma *= crossSection()/ sumOfWeights() /picobarn;
       error *= crossSection()/ sumOfWeights() /picobarn; 
       Scatter2D temphisto(refData(1, 1, 4));
-      Scatter2DPtr  mult = bookScatter2D(1, 1, 4);
+      Scatter2DPtr  mult;
+      book(mult, 1, 1, 4);
       for (size_t b = 0; b < temphisto.numPoints(); b++) {
 	const double x  = temphisto.point(b).x();
 	pair<double,double> ex = temphisto.point(b).xErrs();
 	pair<double,double> ex2 = ex;
 	if(ex2.first ==0.) ex2. first=0.0001;
 	if(ex2.second==0.) ex2.second=0.0001;
 	if (inRange(sqrtS()/GeV, x-ex2.first, x+ex2.second)) {
 	  mult->addPoint(x, sigma, ex, make_pair(error,error));
 	}
 	else {
 	  mult->addPoint(x, 0., ex, make_pair(0.,.0));
 	}
       }
     }
 
     //@}
 
 
     /// @name Histograms
     //@{
     CounterPtr _nkaon;
     //@}
 
 
   };
 
 
   // The hook for the plugin system
   DECLARE_RIVET_PLUGIN(BABAR_2015_I1383130);
 
 
 }
diff --git a/analyses/pluginBABAR/BABAR_2017_I1511276.cc b/analyses/pluginBABAR/BABAR_2017_I1511276.cc
--- a/analyses/pluginBABAR/BABAR_2017_I1511276.cc
+++ b/analyses/pluginBABAR/BABAR_2017_I1511276.cc
@@ -1,164 +1,165 @@
 // -*- C++ -*-
 #include "Rivet/Analysis.hh"
 #include "Rivet/Projections/FinalState.hh"
 #include "Rivet/Projections/UnstableParticles.hh"
 
 namespace Rivet {
 
 
   /// @brief Add a short analysis description here
   class BABAR_2017_I1511276 : public Analysis {
   public:
 
     /// Constructor
     DEFAULT_RIVET_ANALYSIS_CTOR(BABAR_2017_I1511276);
 
 
     /// @name Analysis methods
     //@{
 
     /// Book histograms and initialise projections before the run
     void init() {
 
       // Initialise and register projections
       declare(FinalState(), "FS");
       declare(UnstableParticles(), "UFS");
 
-      _nKKpi   = bookCounter("TMP/KKpi");
-      _nPhipi  = bookCounter("TMP/Phipi");
-      _nKKeta  = bookCounter("TMP/KKeta");
-      _nKKpipi = bookCounter("TMP/KKpipi");;
+      book(_nKKpi  , "TMP/KKpi");
+      book(_nPhipi , "TMP/Phipi");
+      book(_nKKeta , "TMP/KKeta");
+      book(_nKKpipi, "TMP/KKpipi");
 
     }
 
     void findChildren(const Particle & p,map<long,int> & nRes, int &ncount) {
-      foreach(const Particle &child, p.children()) {
+      for(const Particle &child : p.children()) {
 	if(child.children().empty()) {
-	  nRes[child.pdgId()]-=1;
+	  nRes[child.pid()]-=1;
 	  --ncount;
 	}
 	else
 	  findChildren(child,nRes,ncount);
       }
     }
 
     /// Perform the per-event analysis
     void analyze(const Event& event) {
       const FinalState& fs = apply<FinalState>(event, "FS");
       map<long,int> nCount;
       int ntotal(0);
-      foreach (const Particle& p, fs.particles()) {
-	nCount[p.pdgId()] += 1;
+      for (const Particle& p : fs.particles()) {
+	nCount[p.pid()] += 1;
 	++ntotal;
       }
       // stable histos
       if( ntotal == 3 && nCount[130] == 1 &&
 	  nCount[310] == 1 && nCount[111] == 1)
-	_nKKpi->fill(event.weight());
+	_nKKpi->fill();
       else if( ntotal == 4 && nCount[130] == 1 &&
 	       nCount[310] == 1 && nCount[111] == 2)
-	_nKKpipi->fill(event.weight());
+	_nKKpipi->fill();
       // unstable particles
       const FinalState& ufs = apply<FinalState>(event, "UFS");
-      foreach (const Particle& p, ufs.particles()) {
+      for (const Particle& p : ufs.particles()) {
 	if(p.children().empty()) continue;
-	if(p.pdgId()!=333 && p.pdgId()!=221) continue;
+	if(p.pid()!=333 && p.pid()!=221) continue;
 	map<long,int> nRes=nCount;
 	int ncount = ntotal;
 	findChildren(p,nRes,ncount);
 	bool matched  = true;
-	if(p.pdgId()==333 && ncount==1) {
+	if(p.pid()==333 && ncount==1) {
 	  for(auto const & val : nRes) {
 	    if(val.first==111) {
 	      if(val.second!=1) {
 		matched = false;
 		break;
 	      }
 	    }
 	    else if(val.second!=0) {
 	      matched = false;
 	      break;
 	    }
 	  }
 	  if(matched)
-	    _nPhipi->fill(event.weight());
+	    _nPhipi->fill();
 	}
-	else if(p.pdgId()==221 && ncount==2) {
+	else if(p.pid()==221 && ncount==2) {
 	  for(auto const & val : nRes) {
 	    if(val.first==130 || val.first==310) {
 	      if(val.second!=1) {
 		matched = false;
 		break;
 	      }
 	    }
 	    else if(val.second!=0) {
 	      matched = false;
 	      break;
 	    }
 	  }
 	  if(matched)
-	    _nKKeta->fill(event.weight());
+	    _nKKeta->fill();
 	}
       }
     }
 
 
     /// Normalise histograms etc., after the run
     void finalize() {
       for(unsigned int ix=1;ix<5;++ix) {
 	double sigma = 0., error = 0.;
 	if(ix==1) {
 	  sigma = _nKKpi->val();
 	  error = _nKKpi->err();
 	}
 	else if (ix==2) {
 	  sigma = _nPhipi->val();
 	  error = _nPhipi->err();
 	}
 	else if (ix==3) {
 	  sigma = _nKKeta->val();
 	  error = _nKKeta->err();
 	}
 	else if (ix==4) {
 	  sigma = _nKKpipi->val();
 	  error = _nKKpipi->err();
 	}
 	  
 	sigma *= crossSection()/ sumOfWeights() /nanobarn;
 	error *= crossSection()/ sumOfWeights() /nanobarn;
 	
 	Scatter2D temphisto(refData(ix, 1, 1));
-	Scatter2DPtr  mult = bookScatter2D(ix, 1, 1);
+	Scatter2DPtr  mult;
+        book(mult, ix, 1, 1);
 	for (size_t b = 0; b < temphisto.numPoints(); b++) {
 	  const double x  = temphisto.point(b).x();
 	  pair<double,double> ex = temphisto.point(b).xErrs();
 	  pair<double,double> ex2 = ex;
 	  if(ex2.first ==0.) ex2. first=0.0001;
 	  if(ex2.second==0.) ex2.second=0.0001;
 	  if (inRange(sqrtS()/GeV, x-ex2.first, x+ex2.second)) {
 	    mult->addPoint(x, sigma, ex, make_pair(error,error));
 	  }
 	  else {
 	    mult->addPoint(x, 0., ex, make_pair(0.,.0));
 	  }
 	}
       }
     }
 
     //@}
 
 
     /// @name Histograms
     //@{
     CounterPtr _nKKpi,_nPhipi,_nKKeta,_nKKpipi;
     //@}
 
 
   };
 
 
   // The hook for the plugin system
   DECLARE_RIVET_PLUGIN(BABAR_2017_I1511276);
 
 
 }
diff --git a/analyses/pluginBABAR/BABAR_2017_I1591716.cc b/analyses/pluginBABAR/BABAR_2017_I1591716.cc
--- a/analyses/pluginBABAR/BABAR_2017_I1591716.cc
+++ b/analyses/pluginBABAR/BABAR_2017_I1591716.cc
@@ -1,143 +1,144 @@
 // -*- C++ -*-
 #include "Rivet/Analysis.hh"
 #include "Rivet/Projections/FinalState.hh"
 #include "Rivet/Projections/UnstableParticles.hh"
 
 namespace Rivet {
 
 
   /// @brief Add a short analysis description here
   class BABAR_2017_I1591716 : public Analysis {
   public:
 
     /// Constructor
     DEFAULT_RIVET_ANALYSIS_CTOR(BABAR_2017_I1591716);
 
 
     /// @name Analysis methods
     //@{
 
     /// Book histograms and initialise projections before the run
     void init() {
 
       // Initialise and register projections
       declare(FinalState(), "FS");
       declare(UnstableParticles(), "UFS");
 
-      _nKKpipi  = bookCounter("TMP/KKpipi");
-      _nKKpieta = bookCounter("TMP/KKpieta");
+      book(_nKKpipi, "TMP/KKpipi");
+      book(_nKKpieta, "TMP/KKpieta");
 
     }
 
     void findChildren(const Particle & p,map<long,int> & nRes, int &ncount) {
-      foreach(const Particle &child, p.children()) {
+      for (const Particle &child : p.children()) {
 	if(child.children().empty()) {
-	  nRes[child.pdgId()]-=1;
+	  nRes[child.pid()]-=1;
 	  --ncount;
 	}
 	else
 	  findChildren(child,nRes,ncount);
       }
     }
 
 
     /// Perform the per-event analysis
     void analyze(const Event& event) {
       const FinalState& fs = apply<FinalState>(event, "FS");
       map<long,int> nCount;
       int ntotal(0);
-      foreach (const Particle& p, fs.particles()) {
-	nCount[p.pdgId()] += 1;
+      for (const Particle& p : fs.particles()) {
+	nCount[p.pid()] += 1;
 	++ntotal;
       }
       // stable histos
       if( ntotal == 4 && nCount[310] == 1 && nCount[111] == 1 &&
 	  ( (nCount[ 321]==1 && nCount[-211]==1) ||
 	    (nCount[-321]==1 && nCount[ 211]==1)))
-	_nKKpipi->fill(event.weight());
+	_nKKpipi->fill();
 
       // unstable particles
       const FinalState& ufs = apply<FinalState>(event, "UFS");
-      foreach (const Particle& p, ufs.particles()) {
+      for (const Particle& p : ufs.particles()) {
 	if(p.children().empty()) continue;
-	if(p.pdgId()!=221) continue;
+	if(p.pid()!=221) continue;
 	map<long,int> nRes=nCount;
 	int ncount = ntotal;
 	findChildren(p,nRes,ncount);
 	bool matched  = true;
-	if(p.pdgId()==221 && ncount==3) {
+	if(p.pid()==221 && ncount==3) {
 	  for(auto const & val : nRes) {
 	    if(val.first==310 || val.first==111) {
 	      if(val.second!=1) {
 		matched = false;
 		break;
 	      }
 	    }
 	    else if(abs(val.first)==321 || abs(val.first)==211)
 	      continue;
 	    else if(val.second!=0) {
 	      matched = false;
 	      break;
 	    }
 	  }
 	  if(matched) {
 	    if((nRes[321]==1 && nRes[-211]==1 && nRes[-321]==0 && nRes[211]==0) ||
 	       (nRes[321]==0 && nRes[-211]==0 && nRes[-321]==1 && nRes[211]==1))
-	    _nKKpieta->fill(event.weight());
+	    _nKKpieta->fill();
 	  }
 	}
       }
     }
 
 
     /// Normalise histograms etc., after the run
     void finalize() {
       for(unsigned int ix=1;ix<3;++ix) {
 	double sigma = 0., error = 0.;
 	if(ix==1) {
 	  sigma = _nKKpipi->val();
 	  error = _nKKpipi->err();
 	}
 	else if (ix==2) {
 	  sigma = _nKKpieta->val();
 	  error = _nKKpieta->err();
 	}
 	  
 	sigma *= crossSection()/ sumOfWeights() /nanobarn;
 	error *= crossSection()/ sumOfWeights() /nanobarn;
 	
 	Scatter2D temphisto(refData(ix, 1, 1));
-	Scatter2DPtr  mult = bookScatter2D(ix, 1, 1);
+	Scatter2DPtr  mult;
+        book(mult, ix, 1, 1);
 	for (size_t b = 0; b < temphisto.numPoints(); b++) {
 	  const double x  = temphisto.point(b).x();
 	  pair<double,double> ex = temphisto.point(b).xErrs();
 	  pair<double,double> ex2 = ex;
 	  if(ex2.first ==0.) ex2. first=0.0001;
 	  if(ex2.second==0.) ex2.second=0.0001;
 	  if (inRange(sqrtS()/GeV, x-ex2.first, x+ex2.second)) {
 	    mult->addPoint(x, sigma, ex, make_pair(error,error));
 	  }
 	  else {
 	    mult->addPoint(x, 0., ex, make_pair(0.,.0));
 	  }
 	}
       }
     }
 
     //@}
 
 
     /// @name Histograms
     //@{
     CounterPtr _nKKpipi,_nKKpieta;
     //@}
 
 
   };
 
 
   // The hook for the plugin system
   DECLARE_RIVET_PLUGIN(BABAR_2017_I1591716);
 
 
 }
diff --git a/analyses/pluginBABAR/BABAR_2017_I1621593.cc b/analyses/pluginBABAR/BABAR_2017_I1621593.cc
--- a/analyses/pluginBABAR/BABAR_2017_I1621593.cc
+++ b/analyses/pluginBABAR/BABAR_2017_I1621593.cc
@@ -1,87 +1,88 @@
 // -*- C++ -*-
 #include "Rivet/Analysis.hh"
 #include "Rivet/Projections/FinalState.hh"
 
 
 namespace Rivet {
 
 
   /// @brief Add a short analysis description here
   class BABAR_2017_I1621593 : public Analysis {
   public:
 
     /// Constructor
     DEFAULT_RIVET_ANALYSIS_CTOR(BABAR_2017_I1621593);
 
 
     /// @name Analysis methods
     //@{
 
     /// Book histograms and initialise projections before the run
     void init() {
 
       // Initialise and register projections
       declare(FinalState(), "FS");
 
-      _num4pi = bookCounter("TMP/num4");
+      book(_num4pi, "TMP/num4");
 
     }
 
 
     /// Perform the per-event analysis
     void analyze(const Event& event) {
       const FinalState& fs = apply<FinalState>(event, "FS");
 
       map<long,int> nCount;
       int ntotal(0);
-      foreach (const Particle& p, fs.particles()) {
-	nCount[p.pdgId()] += 1;
+      for (const Particle& p : fs.particles()) {
+	nCount[p.pid()] += 1;
 	++ntotal;
       }
       if(ntotal!=4) vetoEvent;
       if(nCount[-211]==1&&nCount[211]==1&&nCount[111]==2)
-	_num4pi->fill(event.weight());
+	_num4pi->fill();
 
     }
 
 
     /// Normalise histograms etc., after the run
     void finalize() {
 
       double sigma = _num4pi->val();
       double error = _num4pi->err();
       sigma *= crossSection()/ sumOfWeights() /nanobarn;
       error *= crossSection()/ sumOfWeights() /nanobarn; 
       Scatter2D temphisto(refData(1, 1, 1));
-      Scatter2DPtr  mult = bookScatter2D(1, 1, 1);
+      Scatter2DPtr  mult;
+      book(mult, 1, 1, 1);
       for (size_t b = 0; b < temphisto.numPoints(); b++) {
 	const double x  = temphisto.point(b).x();
 	pair<double,double> ex = temphisto.point(b).xErrs();
 	pair<double,double> ex2 = ex;
 	if(ex2.first ==0.) ex2. first=0.0001;
 	if(ex2.second==0.) ex2.second=0.0001;
 	if (inRange(sqrtS()/GeV, x-ex2.first, x+ex2.second)) {
 	  mult->addPoint(x, sigma, ex, make_pair(error,error));
 	}
 	else {
 	  mult->addPoint(x, 0., ex, make_pair(0.,.0));
 	}
       }
     }
 
     //@}
 
     /// @name Histograms
     //@{
     CounterPtr _num4pi;
     //@}
 
 
   };
 
 
   // The hook for the plugin system
   DECLARE_RIVET_PLUGIN(BABAR_2017_I1621593);
 
 
 }
diff --git a/analyses/pluginBABAR/BABAR_2018_I1647139.cc b/analyses/pluginBABAR/BABAR_2018_I1647139.cc
--- a/analyses/pluginBABAR/BABAR_2018_I1647139.cc
+++ b/analyses/pluginBABAR/BABAR_2018_I1647139.cc
@@ -1,122 +1,123 @@
 // -*- C++ -*-
 #include "Rivet/Analysis.hh"
 #include "Rivet/Projections/FinalState.hh"
 #include "Rivet/Projections/UnstableParticles.hh"
 
 namespace Rivet {
 
 
   /// @brief Add a short analysis description here
   class BABAR_2018_I1647139 : public Analysis {
   public:
 
     /// Constructor
     DEFAULT_RIVET_ANALYSIS_CTOR(BABAR_2018_I1647139);
 
 
     /// @name Analysis methods
     //@{
 
     /// Book histograms and initialise projections before the run
     void init() {
 
       // Initialise and register projections
       declare(FinalState(), "FS");
       declare(UnstableParticles(), "UFS");
-      _numEtaPiPi = bookCounter("TMP/EtaPiPi");
+      book(_numEtaPiPi, "TMP/EtaPiPi");
 
     }
 
 
     void findChildren(const Particle & p,map<long,int> & nRes, int &ncount) {
-      foreach(const Particle &child, p.children()) {
+      for (const Particle &child : p.children()) {
 	if(child.children().empty()) {
-	  --nRes[child.pdgId()];
+	  --nRes[child.pid()];
 	  --ncount;
 	}
 	else
 	  findChildren(child,nRes,ncount);
       }
     }
 
     /// Perform the per-event analysis
     void analyze(const Event& event) {
       const FinalState& fs = apply<FinalState>(event, "FS");
 
       map<long,int> nCount;
       int ntotal(0);
-      foreach (const Particle& p, fs.particles()) {
-	nCount[p.pdgId()] += 1;
+      for (const Particle& p : fs.particles()) {
+	nCount[p.pid()] += 1;
 	++ntotal;
       }
       const FinalState& ufs = apply<FinalState>(event, "UFS");
-      foreach (const Particle& p, ufs.particles()) {
+      for (const Particle& p : ufs.particles()) {
 	if(p.children().empty()) continue;
 	// find the omega
-	if(p.pdgId()==221) {
+	if(p.pid()==221) {
 	  map<long,int> nRes = nCount;
 	  int ncount = ntotal;
 	  findChildren(p,nRes,ncount);
 	  // eta pi+pi-
 	  if(ncount!=2) continue;
 	  bool matched = true;
 	  for(auto const & val : nRes) {
 	    if(abs(val.first)==211) {
 	      if(val.second !=1) {
 		matched = false;
 		break;
 	      }
 	    }
 	    else if(val.second!=0) {
 	      matched = false;
 	      break;
 	    }
 	  }
 	  if(matched)
-	    _numEtaPiPi->fill(event.weight());
+	    _numEtaPiPi->fill();
 	}
       }
     }
 
 
     /// Normalise histograms etc., after the run
     void finalize() {
 
       double sigma = _numEtaPiPi->val();
       double error = _numEtaPiPi->err();
       sigma *= crossSection()/ sumOfWeights() /nanobarn;
       error *= crossSection()/ sumOfWeights() /nanobarn; 
       Scatter2D temphisto(refData(1, 1, 1));
-      Scatter2DPtr  mult = bookScatter2D(1, 1, 1);
+      Scatter2DPtr  mult;
+      book(mult, 1, 1, 1);
       for (size_t b = 0; b < temphisto.numPoints(); b++) {
 	const double x  = temphisto.point(b).x();
 	pair<double,double> ex = temphisto.point(b).xErrs();
 	pair<double,double> ex2 = ex;
 	if(ex2.first ==0.) ex2. first=0.0001;
 	if(ex2.second==0.) ex2.second=0.0001;
 	if (inRange(sqrtS()/GeV, x-ex2.first, x+ex2.second)) {
 	  mult->addPoint(x, sigma, ex, make_pair(error,error));
 	}
 	else {
 	  mult->addPoint(x, 0., ex, make_pair(0.,.0));
 	}
       }
     }
 
     //@}
 
 
     /// @name Histograms
     //@{
     CounterPtr _numEtaPiPi;
     //@}
 
 
   };
 
 
   // The hook for the plugin system
   DECLARE_RIVET_PLUGIN(BABAR_2018_I1647139);
 
 
 }
diff --git a/analyses/pluginBABAR/BABAR_2018_I1679886.cc b/analyses/pluginBABAR/BABAR_2018_I1679886.cc
--- a/analyses/pluginBABAR/BABAR_2018_I1679886.cc
+++ b/analyses/pluginBABAR/BABAR_2018_I1679886.cc
@@ -1,99 +1,99 @@
 // -*- C++ -*-
 #include "Rivet/Analysis.hh"
 #include "Rivet/Projections/UnstableParticles.hh"
 
 namespace Rivet {
 
 
   /// @brief Add a short analysis description here
   class BABAR_2018_I1679886 : public Analysis {
   public:
 
     /// Constructor
     DEFAULT_RIVET_ANALYSIS_CTOR(BABAR_2018_I1679886);
 
 
     /// @name Analysis methods
     //@{
 
     /// Book histograms and initialise projections before the run
     void init() {
 
       declare(UnstableParticles(), "UFS");
-      _h_KK   = bookHisto1D( 1, 1, 1);
+      book(_h_KK, 1, 1, 1);
 
     }
 
     void findDecayProducts(const Particle & mother, unsigned int & nstable,
                            unsigned int & nK0, unsigned int & nKp,
 			   unsigned int & nKm, FourMomentum & ptot) {
       for(const Particle & p : mother.children()) {
-        int id = p.pdgId();
+        int id = p.pid();
         if ( id == PID::KPLUS ) {
 	  ++nKp;
           ++nstable;
 	  ptot += p.momentum();
 	}
         else if (id == PID::KMINUS ) {
 	  ++nKm;
           ++nstable;
 	  ptot += p.momentum();
 	}
         else if (id == PID::K0S) {
           ++nK0;
           ++nstable;
 	  ptot += p.momentum();
         }
         else if (id == PID::PI0 || id == PID::PIPLUS || id == PID::PIMINUS) {
           ++nstable;
         }
         else if ( !p.children().empty() ) {
           findDecayProducts(p, nstable, nK0, nKp, nKm, ptot);
         }
         else
           ++nstable;
       }
     }
 
     /// Perform the per-event analysis
     void analyze(const Event& event) {
 
       // Loop over taus
       for(const Particle& tau : apply<UnstableParticles>(event, "UFS").particles(Cuts::abspid==PID::TAU)) {
         unsigned int nstable(0),nK0(0),nKp(0),nKm(0);
       	FourMomentum p_tot(0,0,0,0);
         findDecayProducts(tau, nstable, nK0, nKp, nKm, p_tot);
-        if (tau.pdgId() < 0) {
+        if (tau.pid() < 0) {
       	  swap(nKp,nKm);
       	}
        	if(nstable!=3) continue;
       	if(nKm==1 && nK0==1 )
-          _h_KK->fill(p_tot.mass(), event.weight());
+          _h_KK->fill(p_tot.mass());
       }
 
 
     }
 
 
     /// Normalise histograms etc., after the run
     void finalize() {
       normalize(_h_KK);
     }
 
     //@}
 
 
     /// @name Histograms
     //@{
     Histo1DPtr _h_KK;
     //@}
 
 
   };
 
 
   // The hook for the plugin system
   DECLARE_RIVET_PLUGIN(BABAR_2018_I1679886);
 
 
 }
diff --git a/analyses/pluginBABAR/BABAR_2018_I1700745.cc b/analyses/pluginBABAR/BABAR_2018_I1700745.cc
--- a/analyses/pluginBABAR/BABAR_2018_I1700745.cc
+++ b/analyses/pluginBABAR/BABAR_2018_I1700745.cc
@@ -1,215 +1,216 @@
 // -*- C++ -*-
 #include "Rivet/Analysis.hh"
 #include "Rivet/Projections/FinalState.hh"
 #include "Rivet/Projections/UnstableParticles.hh"
 
 namespace Rivet {
 
 
   /// @brief Add a short analysis description here
   class BABAR_2018_I1700745 : public Analysis {
   public:
 
     /// Constructor
     DEFAULT_RIVET_ANALYSIS_CTOR(BABAR_2018_I1700745);
 
 
     /// @name Analysis methods
     //@{
 
     /// Book histograms and initialise projections before the run
     void init() {
 
 
       // Initialise and register projections
       declare(FinalState(), "FS");
       declare(UnstableParticles(), "UFS");
-      _num5Pi        = bookCounter("TMP/5Pi");
-      _num2PiEta     = bookCounter("TMP/2PiEta");
-      _numOmegaPiPi  = bookCounter("TMP/OmegaPiPi");
-      _num4PiEta     = bookCounter("TMP/4PiEta");
-      _numOmegaPiEta = bookCounter("TMP/OmegaPiEta");
+      book(_num5Pi       , "TMP/5Pi");
+      book(_num2PiEta    , "TMP/2PiEta");
+      book(_numOmegaPiPi , "TMP/OmegaPiPi");
+      book(_num4PiEta    , "TMP/4PiEta");
+      book(_numOmegaPiEta, "TMP/OmegaPiEta");
     }
     
     void findChildren(const Particle & p,map<long,int> & nRes, int &ncount) {
-      foreach(const Particle &child, p.children()) {
+      for(const Particle &child : p.children()) {
 	if(child.children().empty()) {
-	  --nRes[child.pdgId()];
+	  --nRes[child.pid()];
 	  --ncount;
 	}
 	else
 	  findChildren(child,nRes,ncount);
       }
     }
 
     /// Perform the per-event analysis
     void analyze(const Event& event) {
       const FinalState& fs = apply<FinalState>(event, "FS");
       map<long,int> nCount;
       int ntotal(0);
-      foreach (const Particle& p, fs.particles()) {
-	nCount[p.pdgId()] += 1;
+      for (const Particle& p : fs.particles()) {
+	nCount[p.pid()] += 1;
 	++ntotal;
       }
       if(ntotal==5 && nCount[211]==1 && nCount[-211]==1 && nCount[111]==3)
-	_num5Pi->fill(event.weight());
+	_num5Pi->fill();
       const FinalState& ufs = apply<FinalState>(event, "UFS");
-      foreach (const Particle& p, ufs.particles()) {
+      for (const Particle& p : ufs.particles()) {
      	if(p.children().empty()) continue;
 	// find eta/omegas
-      	if(p.pdgId()==221 || p.pdgId()==223 ) {
+      	if(p.pid()==221 || p.pid()==223 ) {
        	  map<long,int> nRes = nCount;
        	  int ncount = ntotal;
        	  findChildren(p,nRes,ncount);
 	  // eta
-	  if(p.pdgId()==221) {
+	  if(p.pid()==221) {
 	    // 2 pi eta
 	    if(ncount==2) {
 	      bool matched = true;
 	      for(auto const & val : nRes) {
 		if(abs(val.first)==211) {
 		  if(val.second !=1) {
 		    matched = false;
 		    break;
 		  }
 		}
 		else if(val.second!=0) {
 		  matched = false;
 		  break;
 		}
 	      }
 	      if(matched)
-		_num2PiEta->fill(event.weight());
+		_num2PiEta->fill();
 	    }
 	    // 4 pi eta
 	    else if(ncount==4) {
 	      bool matched = true;
 	      for(auto const & val : nRes) {
 		if(abs(val.first)==211) {
 		  if(val.second !=1) {
 		    matched = false;
 		    break;
 		  }
 		}
 		else if(abs(val.first)==111) {
 		  if(val.second !=2) {
 		    matched = false;
 		    break;
 		  }
 		}
 		else if(val.second!=0) {
 		  matched = false;
 		  break;
 		}
 	      }
 	      if(matched)
-		_num4PiEta->fill(event.weight());
+		_num4PiEta->fill();
 	    }
 	    // pi0 omega eta
-	    foreach (const Particle& p2, ufs.particles()) {
-	      if(p2.pdgId()!=223) continue;
+	    for (const Particle& p2 : ufs.particles()) {
+	      if(p2.pid()!=223) continue;
 	      map<long,int> nResB = nRes;
 	      int ncountB = ncount;
 	      findChildren(p2,nResB,ncountB);
 	      if(ncountB!=1) continue;
 	      bool matched = true;
 	      for(auto const & val : nResB) {
 		if(abs(val.first)==111) {
 		  if(val.second !=1) {
 		    matched = false;
 		    break;
 		  }
 		}
 		else if(val.second!=0) {
 		  matched = false;
 		  break;
 		}
 	      }
 	      if(matched) {
-		_numOmegaPiEta->fill(event.weight());
+		_numOmegaPiEta->fill();
 		break;
 	      }
 	    }
 	  }
 	  else {
 	    if(ncount!=2) continue;	    
 	    bool matched = true;
 	    for(auto const & val : nRes) {
 	      if(abs(val.first)==111) {
 		if(val.second !=2) {
 		  matched = false;
 		  break;
 		}
 	      }
 	      else if(val.second!=0) {
 		matched = false;
 		break;
 	      }
 	    }
 	    if(matched)
-	      _numOmegaPiPi->fill(event.weight());
+	      _numOmegaPiPi->fill();
 	  }
 	}
       }
     }
 
     /// Normalise histograms etc., after the run
     void finalize() {
       for(unsigned int ix=1;ix<6;++ix) {
 	double sigma = 0., error = 0.;
 	if(ix==1) {
 	  sigma = _num5Pi->val();
 	  error = _num5Pi->err();
 	}
 	else if(ix==2) {
 	  sigma = _num2PiEta->val();
 	  error = _num2PiEta->err();
 	}
 	else if(ix==3) {
 	  sigma = _numOmegaPiPi->val();
 	  error = _numOmegaPiPi->err();
 	}
 	else if(ix==4) {
 	  sigma = _num4PiEta->val();
 	  error = _num4PiEta->err();
 	}
 	else if(ix==5) {
 	  sigma = _numOmegaPiEta->val();
 	  error = _numOmegaPiEta->err();
 	}
 	sigma *= crossSection()/ sumOfWeights() /nanobarn;
 	error *= crossSection()/ sumOfWeights() /nanobarn; 
 	Scatter2D temphisto(refData(ix, 1, 1));
-	Scatter2DPtr  mult = bookScatter2D(ix, 1, 1);
+	Scatter2DPtr  mult;
+        book(mult, ix, 1, 1);
 	for (size_t b = 0; b < temphisto.numPoints(); b++) {
 	  const double x  = temphisto.point(b).x();
 	  pair<double,double> ex = temphisto.point(b).xErrs();
 	  pair<double,double> ex2 = ex;
 	  if(ex2.first ==0.) ex2. first=0.0001;
 	  if(ex2.second==0.) ex2.second=0.0001;
 	  if (inRange(sqrtS()/GeV, x-ex2.first, x+ex2.second)) {
 	    mult->addPoint(x, sigma, ex, make_pair(error,error));
 	  }
 	  else {
 	    mult->addPoint(x, 0., ex, make_pair(0.,.0));
 	  }
 	}
       }
     }
     //@}
 
 
     /// @name Histograms
     //@{
     CounterPtr _num5Pi,_num2PiEta,_numOmegaPiPi,
       _num4PiEta,_numOmegaPiEta;
     //@}
 
   };
 
 
   // The hook for the plugin system
   DECLARE_RIVET_PLUGIN(BABAR_2018_I1700745);
 
 
 }
diff --git a/analyses/pluginBELLE/BELLE_2007_I723333.cc b/analyses/pluginBELLE/BELLE_2007_I723333.cc
--- a/analyses/pluginBELLE/BELLE_2007_I723333.cc
+++ b/analyses/pluginBELLE/BELLE_2007_I723333.cc
@@ -1,141 +1,142 @@
 // -*- C++ -*-
 #include "Rivet/Analysis.hh"
 #include "Rivet/Projections/FinalState.hh"
 #include "Rivet/Projections/UnstableParticles.hh"
 
 namespace Rivet {
 
 
   /// @brief Add a short analysis description here
   class BELLE_2007_I723333 : public Analysis {
   public:
 
     /// Constructor
     DEFAULT_RIVET_ANALYSIS_CTOR(BELLE_2007_I723333);
 
 
     /// @name Analysis methods
     //@{
 
     /// Book histograms and initialise projections before the run
     void init() {
 
       // Initialise and register projections
       declare(FinalState(), "FS");
       declare(UnstableParticles(), "UFS");
-      _nDSS = bookCounter("/TMP/nDSS");
-      _nDS = bookCounter("/TMP/nDS");
+      book(_nDSS, "/TMP/nDSS");
+      book(_nDS, "/TMP/nDS");
     }
 
     void findChildren(const Particle & p,map<long,int> & nRes, int &ncount) {
-      foreach(const Particle &child, p.children()) {
+      for(const Particle &child : p.children()) {
 	if(child.children().empty()) {
-	  nRes[child.pdgId()]-=1;
+	  nRes[child.pid()]-=1;
 	  --ncount;
 	}
 	else
 	  findChildren(child,nRes,ncount);
       }
     }
 
     /// Perform the per-event analysis
     void analyze(const Event& event) {
       const FinalState& fs = apply<FinalState>(event, "FS");
 
       map<long,int> nCount;
       int ntotal(0);
-      foreach (const Particle& p, fs.particles()) {
-	nCount[p.pdgId()] += 1;
+      for (const Particle& p : fs.particles()) {
+	nCount[p.pid()] += 1;
 	++ntotal;
       }
       const FinalState& ufs = apply<FinalState>(event, "UFS");
 
       for(unsigned int ix=0;ix<ufs.particles().size();++ix) {
 	const Particle& p1 = ufs.particles()[ix];
-	if(abs(p1.pdgId())!=413) continue;
+	if(abs(p1.pid())!=413) continue;
 	map<long,int> nRes = nCount;
 	int ncount = ntotal;
 	findChildren(p1,nRes,ncount);
 	bool matched=false;
-	int sign = -p1.pdgId()/abs(p1.pdgId());
+	int sign = -p1.pid()/abs(p1.pid());
 	for(unsigned int iy=0;iy<ufs.particles().size();++iy) {
 	  if(ix==iy) continue;
 	  const Particle& p2 = ufs.particles()[iy];
-	  if(!p2.parents().empty() && p2.parents()[0].pdgId()==p1.pdgId())
+	  if(!p2.parents().empty() && p2.parents()[0].pid()==p1.pid())
 	    continue;
-	  if(p2.pdgId()!=sign*413 && p2.pdgId()!=sign*411) continue;
+	  if(p2.pid()!=sign*413 && p2.pid()!=sign*411) continue;
 	  map<long,int> nRes2 = nRes;
 	  int ncount2 = ncount;
 	  findChildren(p2,nRes2,ncount2);
 	  if(ncount2!=0) continue;
 	  matched=true;
 	  for(auto const & val : nRes2) {
 	    if(val.second!=0) {
 	      matched = false;
 	      break;
 	    }
 	  }
 	  if(matched) {
-	    sign = abs(p2.pdgId());
+	    sign = abs(p2.pid());
 	    break;
 	  }
 	}
 	if(matched) {
 	  if(sign==411)
-	    _nDS->fill(event.weight());
+	    _nDS->fill();
 	  else if(sign==413)
-	    _nDSS->fill(event.weight());
+	    _nDSS->fill();
 	}
       }
     }
 
 
     /// Normalise histograms etc., after the run
     void finalize() {
       for(unsigned int ix=1;ix<3;++ix) {
 	double sigma,error;
 	if(ix==1) {
 	  sigma = _nDSS->val();
 	  error = _nDSS->err();
 	}
 	else {
 	  sigma = _nDS->val();
 	  error = _nDS->err();
 	}
     	sigma *= crossSection()/ sumOfWeights() /nanobarn;
     	error *= crossSection()/ sumOfWeights() /nanobarn; 
 	Scatter2D temphisto(refData(ix, 1, 1));
-    	Scatter2DPtr  mult = bookScatter2D(ix, 1, 1);
+    	Scatter2DPtr  mult;
+        book(mult, ix, 1, 1);
 	for (size_t b = 0; b < temphisto.numPoints(); b++) {
 	  const double x  = temphisto.point(b).x();
 	  pair<double,double> ex = temphisto.point(b).xErrs();
 	  pair<double,double> ex2 = ex;
 	  if(ex2.first ==0.) ex2. first=0.0001;
 	  if(ex2.second==0.) ex2.second=0.0001;
 	  if (inRange(sqrtS()/GeV, x-ex2.first, x+ex2.second)) {
 	    mult->addPoint(x, sigma, ex, make_pair(error,error));
 	  }
 	  else {
 	    mult->addPoint(x, 0., ex, make_pair(0.,.0));
 	  }
 	}
       }
     }
 
     //@}
 
 
     /// @name Histograms
     //@{
     CounterPtr _nDSS,_nDS;
     //@}
 
 
   };
 
 
   // The hook for the plugin system
   DECLARE_RIVET_PLUGIN(BELLE_2007_I723333);
 
 
 }
diff --git a/analyses/pluginBELLE/BELLE_2007_I753243.cc b/analyses/pluginBELLE/BELLE_2007_I753243.cc
--- a/analyses/pluginBELLE/BELLE_2007_I753243.cc
+++ b/analyses/pluginBELLE/BELLE_2007_I753243.cc
@@ -1,96 +1,96 @@
 // -*- C++ -*-
 #include "Rivet/Analysis.hh"
 #include "Rivet/Projections/UnstableParticles.hh"
 
 namespace Rivet {
 
 
   /// @brief Add a short analysis description here
   class BELLE_2007_I753243 : public Analysis {
   public:
 
     /// Constructor
     DEFAULT_RIVET_ANALYSIS_CTOR(BELLE_2007_I753243);
 
 
     /// @name Analysis methods
     //@{
 
     /// Book histograms and initialise projections before the run
     void init() {
 
       declare(UnstableParticles(), "UFS");
-      _hist_Kpi = bookHisto1D( 1, 1, 1);
+      book(_hist_Kpi, 1, 1, 1);
 
     }
 
     void findDecayProducts(const Particle & mother, unsigned int & nstable,
                            unsigned int & npip, unsigned int & npim,
                            unsigned int & nK, FourMomentum & ptot) {
       for(const Particle & p : mother.children()) {
-        int id = p.pdgId();
+        int id = p.pid();
         if (id == PID::K0S ) {
 	  ++nK;
           ++nstable;
 	  ptot += p.momentum();
 	}
         else if (id == PID::PIPLUS) {
           ++npip;
           ++nstable;
 	  ptot += p.momentum();
         }
         else if (id == PID::PIMINUS) {
           ++npim;
           ++nstable;
 	  ptot += p.momentum();
         }
         else if (id == PID::PI0 || id == PID::KPLUS ||
 		 id == PID::KMINUS) {
           ++nstable;
         }
         else if ( !p.children().empty() ) {
           findDecayProducts(p, nstable, npip, npim, nK,ptot);
         }
         else
           ++nstable;
       }
     }
 
     /// Perform the per-event analysis
     void analyze(const Event& event) {
 
       // Loop over taus
       for(const Particle& tau : apply<UnstableParticles>(event, "UFS").particles(Cuts::abspid==PID::TAU)) {
         unsigned int nstable(0),npip(0),npim(0),nK(0);
 	FourMomentum p_tot(0,0,0,0);
         findDecayProducts(tau, nstable, npip, npim, nK, p_tot);
-        if (tau.pdgId() < 0) swap(npip, npim);
+        if (tau.pid() < 0) swap(npip, npim);
 	if(nstable==3 && npim==1 && nK==1)
-          _hist_Kpi->fill(p_tot.mass(), event.weight());
+          _hist_Kpi->fill(p_tot.mass());
       }
     }
 
 
     /// Normalise histograms etc., after the run
     void finalize() {
 
       normalize(_hist_Kpi);
     }
 
     //@}
 
 
     /// @name Histograms
     //@{
     Histo1DPtr _hist_Kpi;
     //@}
 
 
   };
 
 
   // The hook for the plugin system
   DECLARE_RIVET_PLUGIN(BELLE_2007_I753243);
 
 
 }
diff --git a/analyses/pluginBELLE/BELLE_2007_I756012.cc b/analyses/pluginBELLE/BELLE_2007_I756012.cc
--- a/analyses/pluginBELLE/BELLE_2007_I756012.cc
+++ b/analyses/pluginBELLE/BELLE_2007_I756012.cc
@@ -1,117 +1,118 @@
 // -*- C++ -*-
 #include "Rivet/Analysis.hh"
 #include "Rivet/Projections/FinalState.hh"
 #include "Rivet/Projections/UnstableParticles.hh"
 
 namespace Rivet {
 
 
   /// @brief Add a short analysis description here
   class BELLE_2007_I756012 : public Analysis {
   public:
 
     /// Constructor
     DEFAULT_RIVET_ANALYSIS_CTOR(BELLE_2007_I756012);
 
 
     /// @name Analysis methods
     //@{
 
     /// Book histograms and initialise projections before the run
     void init() {
       declare(FinalState(), "FS");
       declare(UnstableParticles(), "UFS");
-      _nJPsi = bookCounter("TMP/jpsi");
+      book(_nJPsi, "TMP/jpsi");
     }
 
     void findChildren(const Particle & p,map<long,int> & nRes, int &ncount) {
-      foreach(const Particle &child, p.children()) {
+      for (const Particle &child : p.children()) {
 	if(child.children().empty()) {
-	  --nRes[child.pdgId()];
+	  --nRes[child.pid()];
 	  --ncount;
 	}
 	else
 	  findChildren(child,nRes,ncount);
       }
     }
 
     /// Perform the per-event analysis
     void analyze(const Event& event) {
       const FinalState& fs = apply<FinalState>(event, "FS");
       map<long,int> nCount;
       int ntotal(0);
-      foreach (const Particle& p, fs.particles()) {
-	nCount[p.pdgId()] += 1;
+      for (const Particle& p : fs.particles()) {
+	nCount[p.pid()] += 1;
 	++ntotal;
       }
       const FinalState& ufs = apply<FinalState>(event, "UFS");
-      foreach (const Particle& p, ufs.particles()) {
+      for (const Particle& p : ufs.particles()) {
 	if(p.children().empty()) continue;
-	if(p.pdgId()!=443) continue;
+	if(p.pid()!=443) continue;
 	// find the J/psi
 	map<long,int> nRes = nCount;
 	int ncount = ntotal;
 	findChildren(p,nRes,ncount);
 	// J/psi pi+pi-
 	if(ncount!=2) continue;
 	bool matched = true;
 	for(auto const & val : nRes) {
 	  if(abs(val.first)==211) {
 	    if(val.second !=1) {
 	      matched = false;
 	      break;
 	    }
 	  }
 	  else if(val.second!=0) {
 	    matched = false;
 	    break;
 	  }
 	}
 	if(matched) {
-	  _nJPsi->fill(event.weight());
+	  _nJPsi->fill();
 	  break;
 	}
       }
     }
 
 
     /// Normalise histograms etc., after the run
     void finalize() {
       double sigma =  _nJPsi->val();
       double error = _nJPsi->err();
       sigma *= crossSection()/ sumOfWeights() /picobarn;
       error *= crossSection()/ sumOfWeights() /picobarn; 
       Scatter2D temphisto(refData(1, 1, 1));
-      Scatter2DPtr  mult = bookScatter2D(1, 1, 1);
+      Scatter2DPtr  mult;
+      book(mult, 1, 1, 1);
       for (size_t b = 0; b < temphisto.numPoints(); b++) {
 	const double x  = temphisto.point(b).x();
 	pair<double,double> ex = temphisto.point(b).xErrs();
 	pair<double,double> ex2 = ex;
 	if(ex2.first ==0.) ex2. first=0.0001;
 	if(ex2.second==0.) ex2.second=0.0001;
 	if (inRange(sqrtS()/GeV, x-ex2.first, x+ex2.second)) {
 	  mult->addPoint(x, sigma, ex, make_pair(error,error));
 	}
 	else {
 	  mult->addPoint(x, 0., ex, make_pair(0.,.0));
 	}
       }
     }
 
     //@}
 
 
     /// @name Histograms
     //@{
     CounterPtr _nJPsi;
     //@}
 
 
   };
 
 
   // The hook for the plugin system
   DECLARE_RIVET_PLUGIN(BELLE_2007_I756012);
 
 
 }
diff --git a/analyses/pluginBELLE/BELLE_2007_I756643.cc b/analyses/pluginBELLE/BELLE_2007_I756643.cc
--- a/analyses/pluginBELLE/BELLE_2007_I756643.cc
+++ b/analyses/pluginBELLE/BELLE_2007_I756643.cc
@@ -1,118 +1,119 @@
 // -*- C++ -*-
 #include "Rivet/Analysis.hh"
 #include "Rivet/Projections/FinalState.hh"
 #include "Rivet/Projections/UnstableParticles.hh"
 
 namespace Rivet {
 
 
   /// @brief Add a short analysis description here
   class BELLE_2007_I756643 : public Analysis {
   public:
 
     /// Constructor
     DEFAULT_RIVET_ANALYSIS_CTOR(BELLE_2007_I756643);
 
 
     /// @name Analysis methods
     //@{
 
     /// Book histograms and initialise projections before the run
     void init() {
       declare(FinalState(), "FS");
       declare(UnstableParticles(), "UFS");
-      _nPsi2s = bookCounter("TMP/psi2s");
+      book(_nPsi2s, "TMP/psi2s");
     }
 
     void findChildren(const Particle & p,map<long,int> & nRes, int &ncount) {
-      foreach(const Particle &child, p.children()) {
+      for (const Particle &child : p.children()) {
 	if(child.children().empty()) {
-	  --nRes[child.pdgId()];
+	  --nRes[child.pid()];
 	  --ncount;
 	}
 	else
 	  findChildren(child,nRes,ncount);
       }
     }
 
     /// Perform the per-event analysis
     void analyze(const Event& event) {
       const FinalState& fs = apply<FinalState>(event, "FS");
       map<long,int> nCount;
       int ntotal(0);
-      foreach (const Particle& p, fs.particles()) {
-	nCount[p.pdgId()] += 1;
+      for (const Particle& p : fs.particles()) {
+	nCount[p.pid()] += 1;
 	++ntotal;
       }
       const FinalState& ufs = apply<FinalState>(event, "UFS");
-      foreach (const Particle& p, ufs.particles()) {
+      for (const Particle& p : ufs.particles()) {
 	if(p.children().empty()) continue;
 	// find the psi(2S)
-	if(p.pdgId()==100443) {
+	if(p.pid()==100443) {
 	  map<long,int> nRes = nCount;
 	  int ncount = ntotal;
 	  findChildren(p,nRes,ncount);
 	  // omega pi+pi-
 	  if(ncount!=2) continue;
 	  bool matched = true;
 	  for(auto const & val : nRes) {
 	    if(abs(val.first)==211) {
 	      if(val.second !=1) {
 		matched = false;
 		break;
 	      }
 	    }
 	    else if(val.second!=0) {
 	      matched = false;
 	      break;
 	    }
 	  }
 	  if(matched) {
-	    _nPsi2s->fill(event.weight());
+	    _nPsi2s->fill();
 	    break;
 	  }
 	}
       }
     }
 
 
     /// Normalise histograms etc., after the run
     void finalize() {
       double sigma =  _nPsi2s->val();
       double error = _nPsi2s->err();
       sigma *= crossSection()/ sumOfWeights() /picobarn;
       error *= crossSection()/ sumOfWeights() /picobarn; 
       Scatter2D temphisto(refData(1, 1, 1));
-      Scatter2DPtr  mult = bookScatter2D(1, 1, 1);
+      Scatter2DPtr  mult;
+      book(mult, 1, 1, 1);
       for (size_t b = 0; b < temphisto.numPoints(); b++) {
 	const double x  = temphisto.point(b).x();
 	pair<double,double> ex = temphisto.point(b).xErrs();
 	pair<double,double> ex2 = ex;
 	if(ex2.first ==0.) ex2. first=0.0001;
 	if(ex2.second==0.) ex2.second=0.0001;
 	if (inRange(sqrtS()/GeV, x-ex2.first, x+ex2.second)) {
 	  mult->addPoint(x, sigma, ex, make_pair(error,error));
 	}
 	else {
 	  mult->addPoint(x, 0., ex, make_pair(0.,.0));
 	}
       }
     }
 
     //@}
 
 
     /// @name Histograms
     //@{
     CounterPtr _nPsi2s;
     //@}
 
 
   };
 
 
   // The hook for the plugin system
   DECLARE_RIVET_PLUGIN(BELLE_2007_I756643);
 
 
 }
diff --git a/analyses/pluginBELLE/BELLE_2008_I757220.cc b/analyses/pluginBELLE/BELLE_2008_I757220.cc
--- a/analyses/pluginBELLE/BELLE_2008_I757220.cc
+++ b/analyses/pluginBELLE/BELLE_2008_I757220.cc
@@ -1,136 +1,137 @@
 // -*- C++ -*-
 #include "Rivet/Analysis.hh"
 #include "Rivet/Projections/FinalState.hh"
 #include "Rivet/Projections/UnstableParticles.hh"
 
 namespace Rivet {
 
 
   /// @brief Add a short analysis description here
   class BELLE_2008_I757220 : public Analysis {
   public:
 
     /// Constructor
     DEFAULT_RIVET_ANALYSIS_CTOR(BELLE_2008_I757220);
 
 
     /// @name Analysis methods
     //@{
 
     /// Book histograms and initialise projections before the run
     void init() {
 
       // Initialise and register projections
       declare(FinalState(), "FS");
       declare(UnstableParticles(), "UFS");
-      _nD0 = bookCounter("/TMP/nD0");
-      _nDp = bookCounter("/TMP/nDp");
+      book(_nD0, "/TMP/nD0");
+      book(_nDp, "/TMP/nDp");
     }
 
     void findChildren(const Particle & p,map<long,int> & nRes, int &ncount) {
-      foreach(const Particle &child, p.children()) {
+      for (const Particle &child : p.children()) {
 	if(child.children().empty()) {
-	  nRes[child.pdgId()]-=1;
+	  nRes[child.pid()]-=1;
 	  --ncount;
 	}
 	else
 	  findChildren(child,nRes,ncount);
       }
     }
 
     /// Perform the per-event analysis
     void analyze(const Event& event) {
       const FinalState& fs = apply<FinalState>(event, "FS");
 
       map<long,int> nCount;
       int ntotal(0);
-      foreach (const Particle& p, fs.particles()) {
-	nCount[p.pdgId()] += 1;
+      for (const Particle& p : fs.particles()) {
+	nCount[p.pid()] += 1;
 	++ntotal;
       }
       const FinalState& ufs = apply<FinalState>(event, "UFS");
 
       for(unsigned int ix=0;ix<ufs.particles().size();++ix) {
 	const Particle& p1 = ufs.particles()[ix];
-	if(abs(p1.pdgId())!=411 && abs(p1.pdgId())!=421)
+	if(abs(p1.pid())!=411 && abs(p1.pid())!=421)
 	  continue;
 	map<long,int> nRes = nCount;
 	int ncount = ntotal;
 	findChildren(p1,nRes,ncount);
 	bool matched=false;
 	for(unsigned int iy=0;iy<ufs.particles().size();++iy) {
 	  if(ix==iy) continue;
 	  const Particle& p2 = ufs.particles()[iy];
-	  if(p2.pdgId()!=-p1.pdgId()) continue;
+	  if(p2.pid()!=-p1.pid()) continue;
 	  map<long,int> nRes2 = nRes;
 	  int ncount2 = ncount;
 	  findChildren(p2,nRes2,ncount2);
 	  if(ncount2!=0) continue;
 	  matched=true;
 	  for(auto const & val : nRes2) {
 	    if(val.second!=0) {
 	      matched = false;
 	      break;
 	    }
 	  }
 	  if(matched) break;
 	}
 	if(matched) {
-	  if(abs(p1.pdgId())==411)
-	    _nDp->fill(event.weight());
-	  else if(abs(p1.pdgId())==421)
-	    _nD0->fill(event.weight());
+	  if(abs(p1.pid())==411)
+	    _nDp->fill();
+	  else if(abs(p1.pid())==421)
+	    _nD0->fill();
 	}
       }
     }
 
 
     /// Normalise histograms etc., after the run
     void finalize() {
       for(unsigned int ix=1;ix<3;++ix) {
 	double sigma,error;
 	if(ix==1) {
 	  sigma = _nD0->val();
 	  error = _nD0->err();
 	}
 	else {
 	  sigma = _nDp->val();
 	  error = _nDp->err();
 	}
     	sigma *= crossSection()/ sumOfWeights() /nanobarn;
     	error *= crossSection()/ sumOfWeights() /nanobarn; 
 	Scatter2D temphisto(refData(ix, 1, 1));
-    	Scatter2DPtr  mult = bookScatter2D(ix, 1, 1);
+    	Scatter2DPtr  mult;
+        book(mult, ix, 1, 1);
 	for (size_t b = 0; b < temphisto.numPoints(); b++) {
 	  const double x  = temphisto.point(b).x();
 	  pair<double,double> ex = temphisto.point(b).xErrs();
 	  pair<double,double> ex2 = ex;
 	  if(ex2.first ==0.) ex2. first=0.0001;
 	  if(ex2.second==0.) ex2.second=0.0001;
 	  if (inRange(sqrtS()/GeV, x-ex2.first, x+ex2.second)) {
 	    mult->addPoint(x, sigma, ex, make_pair(error,error));
 	  }
 	  else {
 	    mult->addPoint(x, 0., ex, make_pair(0.,.0));
 	  }
 	}
       }
     }
 
     //@}
 
 
     /// @name Histograms
     //@{
     CounterPtr _nD0,_nDp;
     //@}
 
 
   };
 
 
   // The hook for the plugin system
   DECLARE_RIVET_PLUGIN(BELLE_2008_I757220);
 
 
 }
diff --git a/analyses/pluginBELLE/BELLE_2008_I759073.cc b/analyses/pluginBELLE/BELLE_2008_I759073.cc
--- a/analyses/pluginBELLE/BELLE_2008_I759073.cc
+++ b/analyses/pluginBELLE/BELLE_2008_I759073.cc
@@ -1,128 +1,129 @@
 // -*- C++ -*-
 #include "Rivet/Analysis.hh"
 #include "Rivet/Projections/FinalState.hh"
 #include "Rivet/Projections/UnstableParticles.hh"
 
 namespace Rivet {
 
 
   /// @brief Add a short analysis description here
   class BELLE_2008_I759073 : public Analysis {
   public:
 
     /// Constructor
     DEFAULT_RIVET_ANALYSIS_CTOR(BELLE_2008_I759073);
 
 
     /// @name Analysis methods
     //@{
 
     /// Book histograms and initialise projections before the run
     void init() {
 
       // Initialise and register projections
       declare(FinalState(), "FS");
       declare(UnstableParticles(), "UFS");
-      _nD0 = bookCounter("/TMP/nD0");
+      book(_nD0, "/TMP/nD0");
     }
 
     void findChildren(const Particle & p,map<long,int> & nRes, int &ncount) {
-      foreach(const Particle &child, p.children()) {
+      for (const Particle &child : p.children()) {
 	if(child.children().empty()) {
-	  nRes[child.pdgId()]-=1;
+	  nRes[child.pid()]-=1;
 	  --ncount;
 	}
 	else
 	  findChildren(child,nRes,ncount);
       }
     }
 
     /// Perform the per-event analysis
     void analyze(const Event& event) {
       const FinalState& fs = apply<FinalState>(event, "FS");
 
       map<long,int> nCount;
       int ntotal(0);
-      foreach (const Particle& p, fs.particles()) {
-	nCount[p.pdgId()] += 1;
+      for (const Particle& p : fs.particles()) {
+	nCount[p.pid()] += 1;
 	++ntotal;
       }
       const FinalState& ufs = apply<FinalState>(event, "UFS");
 
 
       for(unsigned int ix=0;ix<ufs.particles().size();++ix) {
 	const Particle& p1 = ufs.particles()[ix];
-	if(abs(p1.pdgId())!=421) continue;
+	if(abs(p1.pid())!=421) continue;
 	map<long,int> nRes = nCount;
 	int ncount = ntotal;
 	findChildren(p1,nRes,ncount);
 	bool matched=false;
-	int id2 = p1.pdgId()>0 ? -411 :  411;
-	int ipi = p1.pdgId()>0 ?  211 : -211;
+	int id2 = p1.pid()>0 ? -411 :  411;
+	int ipi = p1.pid()>0 ?  211 : -211;
 	for(unsigned int iy=0;iy<ufs.particles().size();++iy) {
 	  if(ix==iy) continue;
 	  const Particle& p2 = ufs.particles()[iy];
-	  if(p2.pdgId()!=id2) continue;
+	  if(p2.pid()!=id2) continue;
 	  map<long,int> nRes2 = nRes;
 	  int ncount2 = ncount;
 	  findChildren(p2,nRes2,ncount2);
 	  if(ncount2!=1) continue;
 	  matched=true;
 	  for(auto const & val : nRes2) {
 	    if(val.first==ipi) {
 	      if(val.second!=1) {
 		matched = false;
 		break;
 	      }
 	    }
 	    else if(val.second!=0) {
 	      matched = false;
 	      break;
 	    }
 	  }
 	  if(matched) break;
 	}
 	if(matched)
-	  _nD0->fill(event.weight());
+	  _nD0->fill();
       }
     }
 
 
     /// Normalise histograms etc., after the run
     void finalize() {
       double sigma = _nD0->val();
       double error = _nD0->err();
       sigma *= crossSection()/ sumOfWeights() /nanobarn;
       error *= crossSection()/ sumOfWeights() /nanobarn; 
       Scatter2D temphisto(refData(1, 1, 1));
-      Scatter2DPtr  mult = bookScatter2D(1, 1, 1);
+      Scatter2DPtr  mult;
+      book(mult, 1, 1, 1);
       for (size_t b = 0; b < temphisto.numPoints(); b++) {
 	const double x  = temphisto.point(b).x();
 	pair<double,double> ex = temphisto.point(b).xErrs();
 	pair<double,double> ex2 = ex;
 	if(ex2.first ==0.) ex2. first=0.0001;
 	if(ex2.second==0.) ex2.second=0.0001;
 	if (inRange(sqrtS()/GeV, x-ex2.first, x+ex2.second)) {
 	  mult->addPoint(x, sigma, ex, make_pair(error,error));
 	}
 	else {
 	  mult->addPoint(x, 0., ex, make_pair(0.,.0));
 	}
       }
     }
 
     //@}
 
     /// @name Histograms
     //@{
     CounterPtr _nD0;
     //@}
 
   };
 
 
   // The hook for the plugin system
   DECLARE_RIVET_PLUGIN(BELLE_2008_I759073);
 
 
 }
diff --git a/analyses/pluginBELLE/BELLE_2008_I764099.cc b/analyses/pluginBELLE/BELLE_2008_I764099.cc
--- a/analyses/pluginBELLE/BELLE_2008_I764099.cc
+++ b/analyses/pluginBELLE/BELLE_2008_I764099.cc
@@ -1,139 +1,140 @@
 // -*- C++ -*-
 #include "Rivet/Analysis.hh"
 #include "Rivet/Projections/FinalState.hh"
 #include "Rivet/Projections/UnstableParticles.hh"
 
 namespace Rivet {
 
 
   /// @brief Add a short analysis description here
   class BELLE_2008_I764099 : public Analysis {
   public:
 
     /// Constructor
     DEFAULT_RIVET_ANALYSIS_CTOR(BELLE_2008_I764099);
 
 
     /// @name Analysis methods
     //@{
 
     /// Book histograms and initialise projections before the run
     void init() {
       declare(FinalState(), "FS");
       declare(UnstableParticles(), "UFS");
-      _nUps1pipi = bookCounter("TMP/nUps1pipi");
-      _nUps2pipi = bookCounter("TMP/nUps2pipi");
-      _nUps3pipi = bookCounter("TMP/nUps3pipi");
-      _nUps1KK   = bookCounter("TMP/nUps1KK");
+      book(_nUps1pipi, "TMP/nUps1pipi");
+      book(_nUps2pipi, "TMP/nUps2pipi");
+      book(_nUps3pipi, "TMP/nUps3pipi");
+      book(_nUps1KK,   "TMP/nUps1KK");
     }
 
     void findChildren(const Particle & p,map<long,int> & nRes, int &ncount) {
-      foreach(const Particle &child, p.children()) {
+      for (const Particle &child : p.children()) {
 	if(child.children().empty()) {
-	  --nRes[child.pdgId()];
+	  --nRes[child.pid()];
 	  --ncount;
 	}
 	else
 	  findChildren(child,nRes,ncount);
       }
     }
 
     /// Perform the per-event analysis
     void analyze(const Event& event) {
       const FinalState& fs = apply<FinalState>(event, "FS");
       map<long,int> nCount;
       int ntotal(0);
-      foreach (const Particle& p, fs.particles()) {
-	nCount[p.pdgId()] += 1;
+      for (const Particle& p : fs.particles()) {
+	nCount[p.pid()] += 1;
 	++ntotal;
       }
       const FinalState& ufs = apply<FinalState>(event, "UFS");
-      foreach (const Particle& p, ufs.particles()) {
+      for (const Particle& p : ufs.particles()) {
 	if(p.children().empty()) continue;
-	if(p.pdgId() !=   553  &&
-	   p.pdgId() != 100553 &&
-	   p.pdgId() != 200553 ) continue;
+	if(p.pid() !=   553  &&
+	   p.pid() != 100553 &&
+	   p.pid() != 200553 ) continue;
 	map<long,int> nRes = nCount;
 	int ncount = ntotal;
 	findChildren(p,nRes,ncount);
 	if(ncount!=2) continue;
 	bool matched = true;
 	for(auto const & val : nRes) {
 	  if(abs(val.first)==321 || abs(val.first)==211) {
 	    continue;
 	  }
 	  else if(val.second!=0) {
 	    matched = false;
 	    break;
 	  }
 	}
 	if(matched) {
 	  if(nRes[211]==1 && nRes[-211]==1 ) {
-	    if(p.pdgId()==553)
-	      _nUps1pipi->fill(event.weight());
-	    if(p.pdgId()==100553)
-	      _nUps2pipi->fill(event.weight());
-	    if(p.pdgId()==200553)
-	      _nUps3pipi->fill(event.weight());
+	    if(p.pid()==553)
+	      _nUps1pipi->fill();
+	    if(p.pid()==100553)
+	      _nUps2pipi->fill();
+	    if(p.pid()==200553)
+	      _nUps3pipi->fill();
 	  }
 	  else if(nRes[321]==1 && nRes[-321]==1) {
-	    if(p.pdgId()==553)
-	      _nUps1KK->fill(event.weight());
+	    if(p.pid()==553)
+	      _nUps1KK->fill();
 	  }	  
 	}
       }
     }
 
 
     /// Normalise histograms etc., after the run
     void finalize() {
       double fact = crossSection()/ sumOfWeights() /picobarn;
       for(unsigned int ix=1;ix<5;++ix) {
 	double sigma,error;
 	if(ix==1) {
 	  sigma = _nUps1pipi->val()*fact;
 	  error = _nUps1pipi->err()*fact;
 	}
 	else if(ix==2) {
 	  sigma = _nUps2pipi->val()*fact;
 	  error = _nUps2pipi->err()*fact;
 	}
 	else if(ix==3) {
 	  sigma = _nUps3pipi->val()*fact;
 	  error = _nUps3pipi->err()*fact;
 	}
 	else if(ix==4) {
 	  sigma = _nUps1KK->val()*fact;
 	  error = _nUps1KK->err()*fact;
 	}
 	Scatter2D temphisto(refData(ix, 1, 1));
-	Scatter2DPtr  mult = bookScatter2D(ix, 1, 1);
+	Scatter2DPtr  mult;
+        book(mult, ix, 1, 1);
 	for (size_t b = 0; b < temphisto.numPoints(); b++) {
 	  const double x  = temphisto.point(b).x();
 	  pair<double,double> ex = temphisto.point(b).xErrs();
 	  pair<double,double> ex2 = ex;
 	  if(ex2.first ==0.) ex2. first=0.0001;
 	  if(ex2.second==0.) ex2.second=0.0001;
 	  if (inRange(sqrtS()/GeV, x-ex2.first, x+ex2.second)) {
 	    mult->addPoint(x, sigma, ex, make_pair(error,error));
 	  }
 	  else {
 	    mult->addPoint(x, 0., ex, make_pair(0.,.0));
 	  }
 	}
       }
     }
 
     //@}
 
     /// @name Histograms
     //@{
     CounterPtr _nUps1pipi,_nUps2pipi,_nUps3pipi,_nUps1KK;
     //@}
 
   };
 
   // The hook for the plugin system
   DECLARE_RIVET_PLUGIN(BELLE_2008_I764099);
 
 }
diff --git a/analyses/pluginBELLE/BELLE_2008_I786560.cc b/analyses/pluginBELLE/BELLE_2008_I786560.cc
--- a/analyses/pluginBELLE/BELLE_2008_I786560.cc
+++ b/analyses/pluginBELLE/BELLE_2008_I786560.cc
@@ -1,104 +1,104 @@
 // -*- C++ -*-
 #include "Rivet/Analysis.hh"
 #include "Rivet/Projections/UnstableParticles.hh"
 
 namespace Rivet {
 
 
   /// @brief BELLE tau lepton to pi pi
   /// @author Peter Richardson
   class BELLE_2008_I786560 : public Analysis {
   public:
 
     BELLE_2008_I786560()
       : Analysis("BELLE_2008_I786560")
     {   }
 
 
     void init() {
       declare(UnstableParticles(), "UFS");
       book(_hist_pipi , 1, 1, 1);
       book(_weight_total, "TMP/weight_total");
       book(_weight_pipi, "TMP/weight_pipi");
     }
 
 
     void analyze(const Event& e) {
       // Find the taus
       Particles taus;
       const UnstableParticles& ufs = apply<UnstableFinalState>(e, "UFS");
       for (const Particle& p : ufs.particles()) {
         if (p.abspid() != PID::TAU) continue;
         _weight_total->fill();
         Particles pip, pim, pi0;
         unsigned int nstable = 0;
         // find the decay products we want
         findDecayProducts(p, nstable, pip, pim, pi0);
         if (p.pid() < 0) {
           swap(pip, pim);
         }
         if (nstable != 3) continue;
         // pipi
         if (pim.size() == 1 && pi0.size() == 1) {
           _weight_pipi->fill();
           _hist_pipi->fill((pi0[0].momentum()+pim[0].momentum()).mass2());
         }
       }
     }
 
 
     void finalize() {
       if (_weight_pipi->val() > 0.) scale(_hist_pipi, 1. / *_weight_pipi);
     }
 
 
   private:
 
     //@{
 
     // Histograms
     Histo1DPtr _hist_pipi;
 
     // Weights counters
     CounterPtr _weight_total, _weight_pipi;
 
     //@}
 
     void findDecayProducts(const Particle &mother,
                            unsigned int & nstable,
                            Particles& pip, Particles& pim,
                            Particles& pi0) {
       for (const Particle &p : mother.children()) {
-        long id = p.pdgId();
+        long id = p.pid();
         if (id == PID::PI0 ) {
           pi0.push_back(p);
           ++nstable;
        	}
         else if (id == PID::K0S)
           ++nstable;
         else if (id == PID::PIPLUS) {
           pip.push_back(p);
           ++nstable;
         }
         else if (id == PID::PIMINUS) {
           pim.push_back(p);
           ++nstable;
         }
         else if (id == PID::KPLUS) {
           ++nstable;
         }
         else if (id == PID::KMINUS) {
           ++nstable;
         }
         else if (!p.children().empty()) {
           findDecayProducts(p, nstable, pip, pim, pi0);
         }
         else  ++nstable;
       }
     }
   };
 
 
   DECLARE_RIVET_PLUGIN(BELLE_2008_I786560);
 
 }
diff --git a/analyses/pluginBELLE/BELLE_2008_I791660.cc b/analyses/pluginBELLE/BELLE_2008_I791660.cc
--- a/analyses/pluginBELLE/BELLE_2008_I791660.cc
+++ b/analyses/pluginBELLE/BELLE_2008_I791660.cc
@@ -1,126 +1,127 @@
 // -*- C++ -*-
 #include "Rivet/Analysis.hh"
 #include "Rivet/Projections/FinalState.hh"
 #include "Rivet/Projections/UnstableParticles.hh"
 
 namespace Rivet {
 
 
   /// @brief Add a short analysis description here
   class BELLE_2008_I791660 : public Analysis {
   public:
 
     /// Constructor
     DEFAULT_RIVET_ANALYSIS_CTOR(BELLE_2008_I791660);
 
 
     /// @name Analysis methods
     //@{
 
     /// Book histograms and initialise projections before the run
     void init() {
 
       // Initialise and register projections
       declare(FinalState(), "FS");
       declare(UnstableParticles(), "UFS");
-      _nLambda = bookCounter("/TMP/nLambda");
+      book(_nLambda, "/TMP/nLambda");
     }
 
     void findChildren(const Particle & p,map<long,int> & nRes, int &ncount) {
-      foreach(const Particle &child, p.children()) {
+      for (const Particle &child : p.children()) {
 	if(child.children().empty()) {
-	  nRes[child.pdgId()]-=1;
+	  nRes[child.pid()]-=1;
 	  --ncount;
 	}
 	else
 	  findChildren(child,nRes,ncount);
       }
     }
 
     /// Perform the per-event analysis
     void analyze(const Event& event) {
       const FinalState& fs = apply<FinalState>(event, "FS");
 
       map<long,int> nCount;
       int ntotal(0);
-      foreach (const Particle& p, fs.particles()) {
-	nCount[p.pdgId()] += 1;
+      for (const Particle& p : fs.particles()) {
+	nCount[p.pid()] += 1;
 	++ntotal;
       }
       const FinalState& ufs = apply<FinalState>(event, "UFS");
 
       for(unsigned int ix=0;ix<ufs.particles().size();++ix) {
 	const Particle& p1 = ufs.particles()[ix];
-	if(abs(p1.pdgId())!=4122) continue;
+	if(abs(p1.pid())!=4122) continue;
 	map<long,int> nRes = nCount;
 	int ncount = ntotal;
 	findChildren(p1,nRes,ncount);
 	bool matched=false;
 	for(unsigned int iy=0;iy<ufs.particles().size();++iy) {
 	  if(ix==iy) continue;
 	  const Particle& p2 = ufs.particles()[iy];
-	  if(p2.pdgId() != -p1.pdgId()) continue;
+	  if(p2.pid() != -p1.pid()) continue;
 	  map<long,int> nRes2 = nRes;
 	  int ncount2 = ncount;
 	  findChildren(p2,nRes2,ncount2);
 	  if(ncount2!=0) continue;
 	  matched=true;
 	  for(auto const & val : nRes2) {
 	    if(val.second!=0) {
 	      matched = false;
 	      break;
 	    }
 	  }
 	  if(matched) {
 	    break;
 	  }
 	}
 	if(matched) {
-	  _nLambda->fill(event.weight());
+	  _nLambda->fill();
 	  break;
 	}
       }
     }
 
 
     /// Normalise histograms etc., after the run
     void finalize() {
 
       double sigma = _nLambda->val();
       double error = _nLambda->err();
       sigma *= crossSection()/ sumOfWeights() /nanobarn;
       error *= crossSection()/ sumOfWeights() /nanobarn; 
       Scatter2D temphisto(refData(1, 1, 1));
-      Scatter2DPtr  mult = bookScatter2D(1, 1, 1);
+      Scatter2DPtr  mult;
+      book(mult, 1, 1, 1);
       for (size_t b = 0; b < temphisto.numPoints(); b++) {
 	const double x  = temphisto.point(b).x();
 	pair<double,double> ex = temphisto.point(b).xErrs();
 	pair<double,double> ex2 = ex;
 	if(ex2.first ==0.) ex2. first=0.0001;
 	if(ex2.second==0.) ex2.second=0.0001;
 	if (inRange(sqrtS()/GeV, x-ex2.first, x+ex2.second)) {
 	  mult->addPoint(x, sigma, ex, make_pair(error,error));
 	}
 	else {
 	  mult->addPoint(x, 0., ex, make_pair(0.,.0));
 	}
       }
     }
 
     //@}
 
 
     /// @name Histograms
     //@{
     CounterPtr _nLambda;
     //@}
 
 
   };
 
 
   // The hook for the plugin system
   DECLARE_RIVET_PLUGIN(BELLE_2008_I791660);
 
 
 }
diff --git a/analyses/pluginBELLE/BELLE_2009_I809630.cc b/analyses/pluginBELLE/BELLE_2009_I809630.cc
--- a/analyses/pluginBELLE/BELLE_2009_I809630.cc
+++ b/analyses/pluginBELLE/BELLE_2009_I809630.cc
@@ -1,149 +1,150 @@
 // -*- C++ -*-
 #include "Rivet/Analysis.hh"
 #include "Rivet/Projections/FinalState.hh"
 #include "Rivet/Projections/UnstableParticles.hh"
 
 namespace Rivet {
 
 
   /// @brief Add a short analysis description here
   class BELLE_2009_I809630 : public Analysis {
   public:
 
     /// Constructor
     DEFAULT_RIVET_ANALYSIS_CTOR(BELLE_2009_I809630);
 
 
     /// @name Analysis methods
     //@{
 
     /// Book histograms and initialise projections before the run
     void init() {
 
       // Initialise and register projections
       declare(FinalState(), "FS");
       declare(UnstableParticles(), "UFS");
-      _cphipippim   = bookCounter("TMP/phipippim");
-      _cphif0       = bookCounter("TMP/phif0");
+      book(_cphipippim, "TMP/phipippim");
+      book(_cphif0 ,    "TMP/phif0");
     }
 
     void findChildren(const Particle & p,map<long,int> & nRes, int &ncount) {
-      foreach(const Particle &child, p.children()) {
+      for(const Particle &child : p.children()) {
 	if(child.children().empty()) {
-	  nRes[child.pdgId()]-=1;
+	  nRes[child.pid()]-=1;
 	  --ncount;
 	}
 	else
 	  findChildren(child,nRes,ncount);
       }
     }
 
 
     /// Perform the per-event analysis
     void analyze(const Event& event) {
 
       const FinalState& fs = apply<FinalState>(event, "FS");
 
       map<long,int> nCount;
       int ntotal(0);
-      foreach (const Particle& p, fs.particles()) {
-	nCount[p.pdgId()] += 1;
+      for (const Particle& p : fs.particles()) {
+	nCount[p.pid()] += 1;
 	++ntotal;
       }
       const FinalState& ufs = apply<FinalState>(event, "UFS");
-      foreach (const Particle& p, ufs.particles()) {
+      for (const Particle& p : ufs.particles()) {
 	if(p.children().empty()) continue;
 	// phi
-	if(p.pdgId()!=333) continue;
+	if(p.pid()!=333) continue;
 	map<long,int> nRes=nCount;
 	int ncount = ntotal;
 	findChildren(p,nRes,ncount);
 	// phi pi+pi-
 	if(ncount==2) {
 	  bool matched = true;
 	  for(auto const & val : nRes) {
 	    if(abs(val.first)==211) {
 	      if(val.second!=1) {
 		matched = false;
 		break;
 	      }
 	    }
 	    else if(val.second!=0) {
 	      matched = false;
 	      break;
 	    }
 	  }
 	  if(matched)
-	    _cphipippim->fill(event.weight());
+	    _cphipippim->fill();
 	}
-	foreach (const Particle& p2, ufs.particles()) {
-	  if(p2.pdgId()!=9010221) continue;
+	for (const Particle& p2 : ufs.particles()) {
+	  if(p2.pid()!=9010221) continue;
 	  if(p2.parents()[0].isSame(p)) continue;
 	  map<long,int> nResB = nRes;
 	  int ncountB = ncount;
 	  findChildren(p2,nResB,ncountB);
 	  if(ncountB!=0) continue;
 	  bool matched2 = true;
 	  for(auto const & val : nResB) {
 	    if(val.second!=0) {
 	      matched2 = false;
 	      break;
 	    }
 	  }
 	  if(matched2) {
-	    _cphif0  ->fill(event.weight());
+	    _cphif0  ->fill();
 	  }
 	}
       }
     }
 
 
     /// Normalise histograms etc., after the run
     void finalize() {
       for(unsigned int ix=1;ix<3;++ix) {
 	double sigma,error;
 	if(ix==1) {
 	  sigma = _cphipippim->val();
 	  error = _cphipippim->err();
 	}
 	else {
 	  sigma = _cphif0->val();
 	  error = _cphif0->err();
 	}
 	sigma *= crossSection()/ sumOfWeights() /nanobarn;
 	error *= crossSection()/ sumOfWeights() /nanobarn;
 	Scatter2D temphisto(refData(1, 1, ix));
-	Scatter2DPtr  mult = bookScatter2D(1, 1, ix);
+	Scatter2DPtr  mult;
+        book(mult, 1, 1, ix);
 	for (size_t b = 0; b < temphisto.numPoints(); b++) {
 	  const double x  = temphisto.point(b).x();
 	  pair<double,double> ex = temphisto.point(b).xErrs();
 	  pair<double,double> ex2 = ex;
 	  if(ex2.first ==0.) ex2. first=0.0001;
 	  if(ex2.second==0.) ex2.second=0.0001;
 	  if (inRange(sqrtS()/GeV, x-ex2.first, x+ex2.second)) {
 	    mult->addPoint(x, sigma, ex, make_pair(error,error));
 	  }
 	  else {
 	    mult->addPoint(x, 0., ex, make_pair(0.,.0));
 	  }
 	}
       }
     }
     //@}
 
 
     /// @name Histograms
     //@{
     CounterPtr _cphipippim;
     CounterPtr _cphif0;
     //@}
 
 
   };
 
 
   // The hook for the plugin system
   DECLARE_RIVET_PLUGIN(BELLE_2009_I809630);
 
 
 }
diff --git a/analyses/pluginBELLE/BELLE_2009_I823878.cc b/analyses/pluginBELLE/BELLE_2009_I823878.cc
--- a/analyses/pluginBELLE/BELLE_2009_I823878.cc
+++ b/analyses/pluginBELLE/BELLE_2009_I823878.cc
@@ -1,127 +1,128 @@
 // -*- C++ -*-
 #include "Rivet/Analysis.hh"
 #include "Rivet/Projections/FinalState.hh"
 #include "Rivet/Projections/UnstableParticles.hh"
 
 namespace Rivet {
 
 
   /// @brief Add a short analysis description here
   class BELLE_2009_I823878 : public Analysis {
   public:
 
     /// Constructor
     DEFAULT_RIVET_ANALYSIS_CTOR(BELLE_2009_I823878);
 
 
     /// @name Analysis methods
     //@{
 
     /// Book histograms and initialise projections before the run
     void init() {
 
       // Initialise and register projections
       declare(FinalState(), "FS");
       declare(UnstableParticles(), "UFS");
 
-      _nMeson[1] =  bookCounter("TMP/phieta");
-      _nMeson[2] =  bookCounter("TMP/phietaprime");
-      _nMeson[3] =  bookCounter("TMP/rhoeta");
-      _nMeson[4] =  bookCounter("TMP/rhoetaprime");
+      book(_nMeson[1], "TMP/phieta");
+      book(_nMeson[2], "TMP/phietaprime");
+      book(_nMeson[3], "TMP/rhoeta");
+      book(_nMeson[4], "TMP/rhoetaprime");
     }
 
     void findChildren(const Particle & p,map<long,int> & nRes, int &ncount) {
-      foreach(const Particle &child, p.children()) {
+      for (const Particle &child : p.children()) {
 	if(child.children().empty()) {
-	  nRes[child.pdgId()]-=1;
+	  nRes[child.pid()]-=1;
 	  --ncount;
 	}
 	else
 	  findChildren(child,nRes,ncount);
       }
     }
     
     /// Perform the per-event analysis
     void analyze(const Event& event) {
       const FinalState& fs = apply<FinalState>(event, "FS");
 
       map<long,int> nCount;
       int ntotal(0);
-      foreach (const Particle& p, fs.particles()) {
-	nCount[p.pdgId()] += 1;
+      for (const Particle& p : fs.particles()) {
+	nCount[p.pid()] += 1;
 	++ntotal;
       }
       const FinalState& ufs = apply<FinalState>(event, "UFS");
-      foreach (const Particle& p, ufs.particles()) {
+      for (const Particle& p : ufs.particles()) {
 	if(p.children().empty()) continue;
-	if(p.pdgId()!=333 && p.pdgId()!=113) continue;
+	if(p.pid()!=333 && p.pid()!=113) continue;
 	map<long,int> nRes=nCount;
 	int ncount = ntotal;
 	findChildren(p,nRes,ncount);
-	foreach (const Particle& p2, ufs.particles()) {
-	  if(p2.pdgId()!=221 && p2.pdgId()!=331 ) continue;
+	for (const Particle& p2 : ufs.particles()) {
+	  if(p2.pid()!=221 && p2.pid()!=331 ) continue;
 	  if(p2.parents()[0].isSame(p)) continue;
 	  map<long,int> nResB = nRes;
 	  int ncountB = ncount;
 	  findChildren(p2,nResB,ncountB);
 	  if(ncountB!=0) continue;
 	  bool matched2 = true;
 	  for(auto const & val : nResB) {
 	    if(val.second!=0) {
 	      matched2 = false;
 	      break;
 	    }
 	  }
 	  if(matched2) {
 	    unsigned int iloc=1;
-	    if(p.pdgId()==113 ) iloc+=2;
-	    if(p2.pdgId()==331) iloc+=1;
-	    _nMeson[iloc]->fill(event.weight());
+	    if(p.pid()==113 ) iloc+=2;
+	    if(p2.pid()==331) iloc+=1;
+	    _nMeson[iloc]->fill();
 	  }
 	}
       }
     }
 
     /// Normalise histograms etc., after the run
     void finalize() {
       for(unsigned int ix=1;ix<5;++ix) {
 	double sigma = _nMeson[ix]->val();
 	double error = _nMeson[ix]->err();
     	sigma *= crossSection()/ sumOfWeights() /femtobarn;
     	error *= crossSection()/ sumOfWeights() /femtobarn;
 
 	Scatter2D temphisto(refData(1, 1, ix));
-	Scatter2DPtr  mult = bookScatter2D(1, 1, ix);
+	Scatter2DPtr  mult;
+        book(mult, 1, 1, ix);
 	for (size_t b = 0; b < temphisto.numPoints(); b++) {
 	  const double x  = temphisto.point(b).x();
 	  pair<double,double> ex = temphisto.point(b).xErrs();
 	  pair<double,double> ex2 = ex;
 	  if(ex2.first ==0.) ex2. first=0.0001;
 	  if(ex2.second==0.) ex2.second=0.0001;
 	  if (inRange(sqrtS()/GeV, x-ex2.first, x+ex2.second)) {
 	    mult->addPoint(x, sigma, ex, make_pair(error,error));
 	  }
 	  else {
 	    mult->addPoint(x, 0., ex, make_pair(0.,.0));
 	  }
 	}
       }
     }
 
     //@}
 
 
     /// @name Histograms
     //@{
     CounterPtr _nMeson[5];
     //@}
 
 
   };
 
 
   // The hook for the plugin system
   DECLARE_RIVET_PLUGIN(BELLE_2009_I823878);
 
 
 }
diff --git a/analyses/pluginBELLE/BELLE_2010_I841618.cc b/analyses/pluginBELLE/BELLE_2010_I841618.cc
--- a/analyses/pluginBELLE/BELLE_2010_I841618.cc
+++ b/analyses/pluginBELLE/BELLE_2010_I841618.cc
@@ -1,117 +1,117 @@
 // -*- C++ -*-
 #include "Rivet/Analysis.hh"
 #include "Rivet/Projections/UnstableParticles.hh"
 
 namespace Rivet {
 
 
   /// @brief Add a short analysis description here
   class BELLE_2010_I841618 : public Analysis {
   public:
 
     /// Constructor
     DEFAULT_RIVET_ANALYSIS_CTOR(BELLE_2010_I841618);
 
 
     /// @name Analysis methods
     //@{
 
     /// Book histograms and initialise projections before the run
     void init() {
 
       declare(UnstableParticles(), "UFS");
-      _h_3pi   = bookHisto1D( 1, 1, 1);
-      _h_Kpipi = bookHisto1D( 2, 1, 1);
-      _h_KKpi  = bookHisto1D( 3, 1, 1);
-      _h_3K    = bookHisto1D( 4, 1, 1);
+      book(_h_3pi,   1, 1, 1);
+      book(_h_Kpipi, 2, 1, 1);
+      book(_h_KKpi,  3, 1, 1);
+      book(_h_3K,    4, 1, 1);
 
     }
 
     void findDecayProducts(const Particle & mother, unsigned int & nstable,
                            unsigned int & npip, unsigned int & npim,
                            unsigned int & nKp, unsigned int & nKm, FourMomentum & ptot) {
       for(const Particle & p : mother.children()) {
-        int id = p.pdgId();
+        int id = p.pid();
         if ( id == PID::KPLUS ) {
 	  ++nKp;
           ++nstable;
 	  ptot += p.momentum();
 	}
         else if (id == PID::KMINUS ) {
 	  ++nKm;
           ++nstable;
 	  ptot += p.momentum();
 	}
         else if (id == PID::PIPLUS) {
           ++npip;
           ++nstable;
 	  ptot += p.momentum();
         }
         else if (id == PID::PIMINUS) {
           ++npim;
           ++nstable;
 	  ptot += p.momentum();
         }
         else if (id == PID::PI0 || id == PID::K0S) {
           ++nstable;
         }
         else if ( !p.children().empty() ) {
           findDecayProducts(p, nstable, npip, npim, nKp, nKm,ptot);
         }
         else
           ++nstable;
       }
     }
     
     /// Perform the per-event analysis
     void analyze(const Event& event) {
 
       // Loop over taus
       for(const Particle& tau : apply<UnstableParticles>(event, "UFS").particles(Cuts::abspid==PID::TAU)) {
         unsigned int nstable(0),npip(0),npim(0),nKp(0),nKm(0);
       	FourMomentum p_tot(0,0,0,0);
         findDecayProducts(tau, nstable, npip, npim, nKp, nKm, p_tot);
-        if (tau.pdgId() < 0) {
+        if (tau.pid() < 0) {
       	  swap(npip, npim);
       	  swap(nKp,nKm);
       	}
        	if(nstable!=4) continue;
       	if(npim==2 && npip==1 )
-          _h_3pi->fill(p_tot.mass(), event.weight());
+          _h_3pi->fill(p_tot.mass());
       	else if(npim==1 && npip==1 && nKm==1)
-          _h_Kpipi->fill(p_tot.mass(), event.weight());
+          _h_Kpipi->fill(p_tot.mass());
       	else if(nKm==1 && nKp==1 && npim==1)
-          _h_KKpi->fill(p_tot.mass(), event.weight());
+          _h_KKpi->fill(p_tot.mass());
       	else if(nKm==2 && nKp==1 )
-          _h_3K->fill(p_tot.mass(), event.weight());
+          _h_3K->fill(p_tot.mass());
       }
     }
 
 
     /// Normalise histograms etc., after the run
     void finalize() {
 
       normalize(_h_3pi); 
       normalize(_h_Kpipi); 
       normalize(_h_KKpi); 
       normalize(_h_3K); 
 
     }
 
     //@}
 
 
     /// @name Histograms
     //@{
     Histo1DPtr _h_3pi, _h_Kpipi, _h_KKpi, _h_3K;
     //@}
 
 
   };
 
 
   // The hook for the plugin system
   DECLARE_RIVET_PLUGIN(BELLE_2010_I841618);
 
 
 }
diff --git a/analyses/pluginBELLE/BELLE_2013_I1225975.cc b/analyses/pluginBELLE/BELLE_2013_I1225975.cc
--- a/analyses/pluginBELLE/BELLE_2013_I1225975.cc
+++ b/analyses/pluginBELLE/BELLE_2013_I1225975.cc
@@ -1,116 +1,117 @@
 // -*- C++ -*-
 #include "Rivet/Analysis.hh"
 #include "Rivet/Projections/FinalState.hh"
 #include "Rivet/Projections/UnstableParticles.hh"
 
 namespace Rivet {
 
 
   /// @brief Add a short analysis description here
   class BELLE_2013_I1225975 : public Analysis {
   public:
 
     /// Constructor
     DEFAULT_RIVET_ANALYSIS_CTOR(BELLE_2013_I1225975);
 
 
     /// @name Analysis methods
     //@{
 
     /// Book histograms and initialise projections before the run
     void init() {
       declare(FinalState(), "FS");
       declare(UnstableParticles(), "UFS");
-      _nJPsi = bookCounter("TMP/jpsi");
+      book(_nJPsi, "TMP/jpsi");
     }
 
     void findChildren(const Particle & p,map<long,int> & nRes, int &ncount) {
-      foreach(const Particle &child, p.children()) {
+      for (const Particle &child : p.children()) {
 	if(child.children().empty()) {
-	  --nRes[child.pdgId()];
+	  --nRes[child.pid()];
 	  --ncount;
 	}
 	else
 	  findChildren(child,nRes,ncount);
       }
     }
 
     /// Perform the per-event analysis
     void analyze(const Event& event) {
       const FinalState& fs = apply<FinalState>(event, "FS");
       map<long,int> nCount;
       int ntotal(0);
-      foreach (const Particle& p, fs.particles()) {
-	nCount[p.pdgId()] += 1;
+      for (const Particle& p : fs.particles()) {
+	nCount[p.pid()] += 1;
 	++ntotal;
       }
       const FinalState& ufs = apply<FinalState>(event, "UFS");
-      foreach (const Particle& p, ufs.particles()) {
+      for (const Particle& p : ufs.particles()) {
 	if(p.children().empty()) continue;
 	// find the omega
-	if(p.pdgId()==443) {
+	if(p.pid()==443) {
 	  map<long,int> nRes = nCount;
 	  int ncount = ntotal;
 	  findChildren(p,nRes,ncount);
 	  // omega pi+pi-
 	  if(ncount!=2) continue;
 	  bool matched = true;
 	  for(auto const & val : nRes) {
 	    if(abs(val.first)==211) {
 	      if(val.second !=1) {
 		matched = false;
 		break;
 	      }
 	    }
 	    else if(val.second!=0) {
 	      matched = false;
 	      break;
 	    }
 	  }
 	  if(matched) {
-	    _nJPsi->fill(event.weight());
+	    _nJPsi->fill();
 	    break;
 	  }
 	}
       }
     }
 
 
     /// Normalise histograms etc., after the run
     void finalize() {
       double sigma =  _nJPsi->val();
       double error = _nJPsi->err();
       sigma *= crossSection()/ sumOfWeights() /picobarn;
       error *= crossSection()/ sumOfWeights() /picobarn; 
       Scatter2D temphisto(refData(1, 1, 1));
-      Scatter2DPtr  mult = bookScatter2D(1, 1, 1);
+      Scatter2DPtr  mult;
+      book(mult, 1, 1, 1);
       for (size_t b = 0; b < temphisto.numPoints(); b++) {
 	const double x  = temphisto.point(b).x();
 	pair<double,double> ex = temphisto.point(b).xErrs();
 	pair<double,double> ex2 = ex;
 	if(ex2.first ==0.) ex2. first=0.0001;
 	if(ex2.second==0.) ex2.second=0.0001;
 	if (inRange(sqrtS()/GeV, x-ex2.first, x+ex2.second)) {
 	  mult->addPoint(x, sigma, ex, make_pair(error,error));
 	}
 	else {
 	  mult->addPoint(x, 0., ex, make_pair(0.,.0));
 	}
       }
     }
 
     //@}
 
 
     /// @name Histograms
     //@{
     CounterPtr _nJPsi;
     //@}
 
 
   };
 
   // The hook for the plugin system
   DECLARE_RIVET_PLUGIN(BELLE_2013_I1225975);
 
 }
diff --git a/analyses/pluginBELLE/BELLE_2014_I1282602.cc b/analyses/pluginBELLE/BELLE_2014_I1282602.cc
--- a/analyses/pluginBELLE/BELLE_2014_I1282602.cc
+++ b/analyses/pluginBELLE/BELLE_2014_I1282602.cc
@@ -1,119 +1,120 @@
 // -*- C++ -*-
 #include "Rivet/Analysis.hh"
 #include "Rivet/Projections/FinalState.hh"
 #include "Rivet/Projections/UnstableParticles.hh"
 
 namespace Rivet {
 
 
   /// @brief Add a short analysis description here
   class BELLE_2014_I1282602 : public Analysis {
   public:
 
     /// Constructor
     DEFAULT_RIVET_ANALYSIS_CTOR(BELLE_2014_I1282602);
 
 
     /// @name Analysis methods
     //@{
 
     /// Book histograms and initialise projections before the run
     void init() {
       declare(FinalState(), "FS");
       declare(UnstableParticles(), "UFS");
-      _nJPsi = bookCounter("TMP/jpsi");
+      book(_nJPsi, "TMP/jpsi");
     }
 
     void findChildren(const Particle & p,map<long,int> & nRes, int &ncount) {
-      foreach(const Particle &child, p.children()) {
+      for (const Particle &child : p.children()) {
 	if(child.children().empty()) {
-	  --nRes[child.pdgId()];
+	  --nRes[child.pid()];
 	  --ncount;
 	}
 	else
 	  findChildren(child,nRes,ncount);
       }
     }
 
 
     /// Perform the per-event analysis
     void analyze(const Event& event) {
       const FinalState& fs = apply<FinalState>(event, "FS");
       map<long,int> nCount;
       int ntotal(0);
-      foreach (const Particle& p, fs.particles()) {
-	nCount[p.pdgId()] += 1;
+      for (const Particle& p : fs.particles()) {
+	nCount[p.pid()] += 1;
 	++ntotal;
       }
       const FinalState& ufs = apply<FinalState>(event, "UFS");
-      foreach (const Particle& p, ufs.particles()) {
+      for (const Particle& p : ufs.particles()) {
 	if(p.children().empty()) continue;
 	// find the j/psi
-	if(p.pdgId()==443) {
+	if(p.pid()==443) {
 	  map<long,int> nRes = nCount;
 	  int ncount = ntotal;
 	  findChildren(p,nRes,ncount);
 	  // J/psi pi+pi-
 	  if(ncount!=2) continue;
 	  bool matched = true;
 	  for(auto const & val : nRes) {
 	    if(abs(val.first)==321) {
 	      if(val.second !=1) {
 		matched = false;
 		break;
 	      }
 	    }
 	    else if(val.second!=0) {
 	      matched = false;
 	      break;
 	    }
 	  }
 	  if(matched) {
-	    _nJPsi->fill(event.weight());
+	    _nJPsi->fill();
 	    break;
 	  }
 	}
       }
     }
 
 
     /// Normalise histograms etc., after the run
     void finalize() {
       double sigma =  _nJPsi->val();
       double error = _nJPsi->err();
       sigma *= crossSection()/ sumOfWeights() /picobarn;
       error *= crossSection()/ sumOfWeights() /picobarn; 
       Scatter2D temphisto(refData(1, 1, 1));
-      Scatter2DPtr  mult = bookScatter2D(1, 1, 1);
+      Scatter2DPtr  mult;
+      book(mult, 1, 1, 1);
       for (size_t b = 0; b < temphisto.numPoints(); b++) {
 	const double x  = temphisto.point(b).x();
 	pair<double,double> ex = temphisto.point(b).xErrs();
 	pair<double,double> ex2 = ex;
 	if(ex2.first ==0.) ex2. first=0.0001;
 	if(ex2.second==0.) ex2.second=0.0001;
 	if (inRange(sqrtS()/GeV, x-ex2.first, x+ex2.second)) {
 	  mult->addPoint(x, sigma, ex, make_pair(error,error));
 	}
 	else {
 	  mult->addPoint(x, 0., ex, make_pair(0.,.0));
 	}
       }
     }
 
     //@}
 
 
     /// @name Histograms
     //@{
     CounterPtr _nJPsi;
     //@}
 
 
   };
 
 
   // The hook for the plugin system
   DECLARE_RIVET_PLUGIN(BELLE_2014_I1282602);
 
 
 }
diff --git a/analyses/pluginBELLE/BELLE_2015_I1324785.cc b/analyses/pluginBELLE/BELLE_2015_I1324785.cc
--- a/analyses/pluginBELLE/BELLE_2015_I1324785.cc
+++ b/analyses/pluginBELLE/BELLE_2015_I1324785.cc
@@ -1,118 +1,119 @@
 // -*- C++ -*-
 #include "Rivet/Analysis.hh"
 #include "Rivet/Projections/FinalState.hh"
 #include "Rivet/Projections/UnstableParticles.hh"
 
 namespace Rivet {
 
 
   /// @brief Add a short analysis description here
   class BELLE_2015_I1324785 : public Analysis {
   public:
 
     /// Constructor
     DEFAULT_RIVET_ANALYSIS_CTOR(BELLE_2015_I1324785);
 
 
     /// @name Analysis methods
     //@{
 
     /// Book histograms and initialise projections before the run
     void init() {
       declare(FinalState(), "FS");
       declare(UnstableParticles(), "UFS");
-      _nPsi2s = bookCounter("TMP/psi2s");
+      book(_nPsi2s, "TMP/psi2s");
     }
 
     void findChildren(const Particle & p,map<long,int> & nRes, int &ncount) {
-      foreach(const Particle &child, p.children()) {
+      for (const Particle &child : p.children()) {
 	if(child.children().empty()) {
-	  --nRes[child.pdgId()];
+	  --nRes[child.pid()];
 	  --ncount;
 	}
 	else
 	  findChildren(child,nRes,ncount);
       }
     }
 
     /// Perform the per-event analysis
     void analyze(const Event& event) {
       const FinalState& fs = apply<FinalState>(event, "FS");
       map<long,int> nCount;
       int ntotal(0);
-      foreach (const Particle& p, fs.particles()) {
-	nCount[p.pdgId()] += 1;
+      for (const Particle& p : fs.particles()) {
+	nCount[p.pid()] += 1;
 	++ntotal;
       }
       const FinalState& ufs = apply<FinalState>(event, "UFS");
-      foreach (const Particle& p, ufs.particles()) {
+      for (const Particle& p : ufs.particles()) {
 	if(p.children().empty()) continue;
 	// find the psi(2S)
-	if(p.pdgId()==100443) {
+	if(p.pid()==100443) {
 	  map<long,int> nRes = nCount;
 	  int ncount = ntotal;
 	  findChildren(p,nRes,ncount);
 	  // omega pi+pi-
 	  if(ncount!=2) continue;
 	  bool matched = true;
 	  for(auto const & val : nRes) {
 	    if(abs(val.first)==211) {
 	      if(val.second !=1) {
 		matched = false;
 		break;
 	      }
 	    }
 	    else if(val.second!=0) {
 	      matched = false;
 	      break;
 	    }
 	  }
 	  if(matched) {
-	    _nPsi2s->fill(event.weight());
+	    _nPsi2s->fill();
 	    break;
 	  }
 	}
       }
     }
 
 
     /// Normalise histograms etc., after the run
     void finalize() {
       double sigma =  _nPsi2s->val();
       double error = _nPsi2s->err();
       sigma *= crossSection()/ sumOfWeights() /picobarn;
       error *= crossSection()/ sumOfWeights() /picobarn; 
       Scatter2D temphisto(refData(1, 1, 1));
-      Scatter2DPtr  mult = bookScatter2D(1, 1, 1);
+      Scatter2DPtr  mult;
+      book(mult, 1, 1, 1);
       for (size_t b = 0; b < temphisto.numPoints(); b++) {
 	const double x  = temphisto.point(b).x();
 	pair<double,double> ex = temphisto.point(b).xErrs();
 	pair<double,double> ex2 = ex;
 	if(ex2.first ==0.) ex2. first=0.0001;
 	if(ex2.second==0.) ex2.second=0.0001;
 	if (inRange(sqrtS()/GeV, x-ex2.first, x+ex2.second)) {
 	  mult->addPoint(x, sigma, ex, make_pair(error,error));
 	}
 	else {
 	  mult->addPoint(x, 0., ex, make_pair(0.,.0));
 	}
       }
     }
 
     //@}
 
 
     /// @name Histograms
     //@{
     CounterPtr _nPsi2s;
     //@}
 
 
   };
 
 
   // The hook for the plugin system
   DECLARE_RIVET_PLUGIN(BELLE_2015_I1324785);
 
 
 }
diff --git a/analyses/pluginBELLE/BELLE_2015_I1330289.cc b/analyses/pluginBELLE/BELLE_2015_I1330289.cc
--- a/analyses/pluginBELLE/BELLE_2015_I1330289.cc
+++ b/analyses/pluginBELLE/BELLE_2015_I1330289.cc
@@ -1,119 +1,119 @@
 // -*- C++ -*-
 #include "Rivet/Analysis.hh"
 #include "Rivet/Projections/UnstableParticles.hh"
 #include "Rivet/Projections/FastJets.hh"
 
 namespace Rivet {
 
 
   /// @brief Add a short analysis description here
   class BELLE_2015_I1330289 : public Analysis {
   public:
 
     /// Constructor
     DEFAULT_RIVET_ANALYSIS_CTOR(BELLE_2015_I1330289);
 
 
     /// @name Analysis methods
     //@{
 
     /// Book histograms and initialise projections before the run
     void init() {
 
       // Initialise and register projections
       declare(UnstableParticles(), "UFS");
 
       // Book histograms
-      _h_spectrum = bookHisto1D(1, 1, 2);
-      _nBottom = 0.;
+      book(_h_spectrum, 1, 1, 2);
+      book(_nBottom, "TMP/BottomCounter");
     }
 
 
     void findDecayProducts(const Particle & mother, unsigned int & nK0,
 			   unsigned int & nKp, unsigned int & nKm,
 			   FourMomentum & ptot) {
       for(const Particle & p : mother.children()) {
-        int id = p.pdgId();
+        int id = p.pid();
         if ( id == PID::KPLUS ) {
 	  ++nKp;
 	  ptot += p.momentum();
 	}
         else if (id == PID::KMINUS ) {
 	  ++nKm;
 	  ptot += p.momentum();
 	}
         else if (id == PID::K0S) {
           ++nK0;
 	  ptot += p.momentum();
         }
         else if (id == PID::PI0 || id == PID::PIPLUS || id == PID::PIMINUS) {
 	  ptot += p.momentum();
         }
         else if ( !p.children().empty() ) {
           findDecayProducts(p, nK0, nKp, nKm, ptot);
         }
         else
 	  ptot += p.momentum();
       }
     }
       
     /// Perform the per-event analysis
     void analyze(const Event& event) {
 
       // Loop over bottoms
       for(const Particle& bottom : apply<UnstableParticles>(event, "UFS").particles()) {
-	if(bottom.pdgId()!=-521 && bottom.pdgId()!=-511) continue;
+	if(bottom.pid()!=-521 && bottom.pid()!=-511) continue;
 	FourMomentum pgamma(0.,0.,0.,0.);
 	unsigned int ngamma = 0;
 	bool fs = true;
-	foreach(const Particle & child, bottom.children()) {
-	  if(child.pdgId()==bottom.pdgId()) {
+	for (const Particle & child : bottom.children()) {
+	  if(child.pid()==bottom.pid()) {
 	    fs = false;
 	    break;
 	  }
-	  else if(child.pdgId()==22) {
+	  else if(child.pid()==22) {
 	    ngamma += 1;
 	    pgamma += child.momentum();
 	  }
 	}
 	if(!fs) continue;
-	_nBottom += event.weight();
+	_nBottom->fill();
 	if(ngamma!=1) continue;
         unsigned int nK0(0),nKp(0),nKm(0);
       	FourMomentum p_tot(0,0,0,0);
         findDecayProducts(bottom, nK0, nKp, nKm, p_tot);
 	unsigned int nk = nKp-nKm+nK0;
 	if(nk%2==1) {
 	  p_tot -= pgamma;
-	  _h_spectrum->fill(p_tot.mass()/GeV,event.weight());
+	  _h_spectrum->fill(p_tot.mass()/GeV);
 	}
       }
 
     }
 
 
     /// Normalise histograms etc., after the run
     void finalize() {
-      scale(_h_spectrum, 1e6/_nBottom);
+      scale(_h_spectrum, 1e6/_nBottom->sumW());
       // multiply by the bin width
       for (unsigned int ix=0;ix<_h_spectrum->numBins();++ix) {
       	_h_spectrum->bins()[ix].scaleW(_h_spectrum->bins()[ix].xWidth());
       }
     }
 
     //@}
 
 
     /// @name Histograms
     //@{
     Histo1DPtr _h_spectrum;
-    double _nBottom;
+    CounterPtr _nBottom;
     //@}
   };
 
 
   // The hook for the plugin system
   DECLARE_RIVET_PLUGIN(BELLE_2015_I1330289);
 
 
 }
diff --git a/analyses/pluginBELLE/BELLE_2016_I1389855.cc b/analyses/pluginBELLE/BELLE_2016_I1389855.cc
--- a/analyses/pluginBELLE/BELLE_2016_I1389855.cc
+++ b/analyses/pluginBELLE/BELLE_2016_I1389855.cc
@@ -1,131 +1,132 @@
 // -*- C++ -*-
 #include "Rivet/Analysis.hh"
 #include "Rivet/Projections/FinalState.hh"
 #include "Rivet/Projections/UnstableParticles.hh"
 
 namespace Rivet {
 
 
   /// @brief Add a short analysis description here
   class BELLE_2016_I1389855 : public Analysis {
   public:
 
     /// Constructor
     DEFAULT_RIVET_ANALYSIS_CTOR(BELLE_2016_I1389855);
 
 
     /// @name Analysis methods
     //@{
 
     /// Book histograms and initialise projections before the run
     void init() {
       declare(FinalState(), "FS");
       declare(UnstableParticles(), "UFS");
-      _nhb1 = bookCounter("TMP/hb1");
-      _nhb2 = bookCounter("TMP/hb2");
+      book(_nhb1, "TMP/hb1");
+      book(_nhb2, "TMP/hb2");
     }
 
     void findChildren(const Particle & p,map<long,int> & nRes, int &ncount) {
-      foreach(const Particle &child, p.children()) {
+      for (const Particle &child : p.children()) {
 	if(child.children().empty()) {
-	  --nRes[child.pdgId()];
+	  --nRes[child.pid()];
 	  --ncount;
 	}
 	else
 	  findChildren(child,nRes,ncount);
       }
     }
 
     /// Perform the per-event analysis
     void analyze(const Event& event) {
 
       const FinalState& fs = apply<FinalState>(event, "FS");
       map<long,int> nCount;
       int ntotal(0);
-      foreach (const Particle& p, fs.particles()) {
-	nCount[p.pdgId()] += 1;
+      for (const Particle& p : fs.particles()) {
+	nCount[p.pid()] += 1;
 	++ntotal;
       }
       const FinalState& ufs = apply<FinalState>(event, "UFS");
-      foreach (const Particle& p, ufs.particles()) {
+      for (const Particle& p : ufs.particles()) {
 	if(p.children().empty()) continue;
 	// find the omega
-	if(p.pdgId()== 10553|| p.pdgId()==110553) {
+	if(p.pid()== 10553|| p.pid()==110553) {
 	  map<long,int> nRes = nCount;
 	  int ncount = ntotal;
 	  findChildren(p,nRes,ncount);
 	  // omega pi+pi-
 	  if(ncount!=2) continue;
 	  bool matched = true;
 	  for(auto const & val : nRes) {
 	    if(abs(val.first)==211) {
 	      if(val.second !=1) {
 		matched = false;
 		break;
 	      }
 	    }
 	    else if(val.second!=0) {
 	      matched = false;
 	      break;
 	    }
 	  }
 	  if(matched) {
-	    if(p.pdgId()== 10553)
-	      _nhb1->fill(event.weight());
+	    if(p.pid()== 10553)
+	      _nhb1->fill();
 	    else
-	      _nhb2->fill(event.weight());
+	      _nhb2->fill();
 	    break;
 	  }
 	}
       }
     }
 
 
     /// Normalise histograms etc., after the run
     void finalize() {
       for(unsigned int ix=2;ix<4;++ix) {
 	double sigma,error;
 	if(ix==2) {
 	  sigma = _nhb1->val();
 	  error = _nhb1->err();
 	}
 	else {
 	  sigma = _nhb2->val();
 	  error = _nhb2->err();
 	}
 	sigma *= crossSection()/ sumOfWeights() /picobarn;
 	error *= crossSection()/ sumOfWeights() /picobarn; 
 	Scatter2D temphisto(refData(1, 1, ix));
-	Scatter2DPtr  mult = bookScatter2D(1, 1, ix);
+	Scatter2DPtr  mult;
+        book(mult, 1, 1, ix);
 	for (size_t b = 0; b < temphisto.numPoints(); b++) {
 	  const double x  = temphisto.point(b).x();
 	  pair<double,double> ex = temphisto.point(b).xErrs();
 	  pair<double,double> ex2 = ex;
 	  if(ex2.first ==0.) ex2. first=0.0001;
 	  if(ex2.second==0.) ex2.second=0.0001;
 	  if (inRange(sqrtS()/MeV, x-ex2.first, x+ex2.second)) {
 	    mult->addPoint(x, sigma, ex, make_pair(error,error));
 	  }
 	  else {
 	    mult->addPoint(x, 0., ex, make_pair(0.,.0));
 	  }
 	}
       }
     }
     //@}
 
 
     /// @name Histograms
     //@{
     CounterPtr _nhb1,_nhb2;
     //@}
 
 
   };
 
 
   // The hook for the plugin system
   DECLARE_RIVET_PLUGIN(BELLE_2016_I1389855);
 
 
 }
diff --git a/analyses/pluginBELLE/BELLE_2017_I1606201.cc b/analyses/pluginBELLE/BELLE_2017_I1606201.cc
--- a/analyses/pluginBELLE/BELLE_2017_I1606201.cc
+++ b/analyses/pluginBELLE/BELLE_2017_I1606201.cc
@@ -1,115 +1,115 @@
 // -*- C++ -*-
 #include "Rivet/Analysis.hh"
 #include "Rivet/Projections/UnstableParticles.hh"
 
 namespace Rivet {
 
 
   /// @brief Add a short analysis description here
   class BELLE_2017_I1606201 : public Analysis {
   public:
 
     /// Constructor
     DEFAULT_RIVET_ANALYSIS_CTOR(BELLE_2017_I1606201);
 
 
     /// @name Analysis methods
     //@{
 
     /// Book histograms and initialise projections before the run
     void init() {
       // Initialise and register projections
       declare(UnstableParticles(), "UFS");
       // Book histograms
       for(unsigned int ix=1;ix<16;++ix)
-	_h[ix] = bookHisto1D(ix, 1, 1);
+	book(_h[ix], ix, 1, 1);
     }
 
 
     /// Perform the per-event analysis
     void analyze(const Event& event) {
       const UnstableParticles& ufs = apply<UnstableParticles>(event, "UFS");
 
-      foreach (const Particle& p, ufs.particles()) {
+      for (const Particle& p : ufs.particles()) {
 	const Vector3 mom3 = p.p3();
 	double pp = mom3.mod();
 	double xp = 2.*pp/sqrtS();
-	int id = abs(p.pdgId());
+	int id = abs(p.pid());
 	if(id==3122)
-	  _h[ 1]->fill(xp,event.weight());
+	  _h[ 1]->fill(xp);
 	else if(id==3212)
-	  _h[ 2]->fill(xp,event.weight());
+	  _h[ 2]->fill(xp);
 	else if(id==3224)
-	  _h[ 3]->fill(xp,event.weight());
+	  _h[ 3]->fill(xp);
 	else if(id==3124)
-	  _h[ 4]->fill(xp,event.weight());
+	  _h[ 4]->fill(xp);
 	else if(id==3312)
-	  _h[ 5]->fill(xp,event.weight());
+	  _h[ 5]->fill(xp);
 	else if(id==3334)
-	  _h[ 6]->fill(xp,event.weight());
+	  _h[ 6]->fill(xp);
 	else if(id==3324)
-	  _h[ 7]->fill(xp,event.weight());
+	  _h[ 7]->fill(xp);
 	else if(id==4122)
-	  _h[ 8]->fill(xp,event.weight());
+	  _h[ 8]->fill(xp);
 	else if(id==14122)
-	  _h[ 9]->fill(xp,event.weight());
+	  _h[ 9]->fill(xp);
 	else if(id==4124)
-	  _h[10]->fill(xp,event.weight());
+	  _h[10]->fill(xp);
 	else if(id==4112)
-	  _h[11]->fill(xp,event.weight());
+	  _h[11]->fill(xp);
 	else if(id==4114)
-	  _h[12]->fill(xp,event.weight());
+	  _h[12]->fill(xp);
 	else if(id==4332) {
 	  if(isDecay(p,{3334,-211})) 
-	    _h[13]->fill(xp,event.weight());
+	    _h[13]->fill(xp);
 	}
 	else if(id==4132) {
 	  if(isDecay(p,{3312,211}))
-	    _h[14]->fill(xp,event.weight());
+	    _h[14]->fill(xp);
 	  else if(isDecay(p,{3334,321}))
-	    _h[15]->fill(xp,event.weight());
+	    _h[15]->fill(xp);
 	}
       }
     }
 
     // Check for explicit decay into pdgids
     bool isDecay(const Particle& mother, vector<int> ids) {
-      if(mother.pdgId()<0) {
+      if(mother.pid()<0) {
 	for(unsigned int ix=0;ix<ids.size();++ix)
 	  ids[ix] *= -1;
       }
       // Trivial check to ignore any other decays but the one in question modulo photons
       const Particles children = mother.children(Cuts::pid!=PID::PHOTON);
       if (children.size()!=ids.size()) return false;
       // Check for the explicit decay
       return all(ids, [&](int i){return count(children, hasPID(i))==1;});
     }
 
     /// Normalise histograms etc., after the run
     void finalize() {
       // norm to cross section
       for(unsigned int ix=1;ix<16;++ix) {
 	if( ix<=4 || (ix>=8 &&ix<=12) ) 
 	  scale(_h[ix], crossSection()/nanobarn/sumOfWeights());
 	else
 	  scale(_h[ix], crossSection()/picobarn/sumOfWeights());
       }
     }
 
     //@}
 
 
     /// @name Histograms
     //@{
     Histo1DPtr _h[16];
     //@}
 
 
   };
 
 
   // The hook for the plugin system
   DECLARE_RIVET_PLUGIN(BELLE_2017_I1606201);
 
 
 }
diff --git a/analyses/pluginBELLE/BELLE_2017_I1613517.cc b/analyses/pluginBELLE/BELLE_2017_I1613517.cc
--- a/analyses/pluginBELLE/BELLE_2017_I1613517.cc
+++ b/analyses/pluginBELLE/BELLE_2017_I1613517.cc
@@ -1,167 +1,168 @@
 // -*- C++ -*-
 #include "Rivet/Analysis.hh"
 #include "Rivet/Projections/FinalState.hh"
 #include "Rivet/Projections/UnstableParticles.hh"
 
 namespace Rivet {
 
 
   /// @brief Add a short analysis description here
   class BELLE_2017_I1613517 : public Analysis {
   public:
 
     /// Constructor
     DEFAULT_RIVET_ANALYSIS_CTOR(BELLE_2017_I1613517);
 
 
     /// @name Analysis methods
     //@{
 
     /// Book histograms and initialise projections before the run
     void init() {
 
       // Initialise and register projections
       declare(FinalState(), "FS");
       declare(UnstableParticles(), "UFS");
 
       // Book histograms
-      _c_DpDmS   = bookCounter("/TMP/sigma_DpDmS");
-      _c_DpSDmS  = bookCounter("/TMP/sigma_DpSDmS");
+      book(_c_DpDmS, "/TMP/sigma_DpDmS");
+      book(_c_DpSDmS, "/TMP/sigma_DpSDmS");
     }
 
     void findChildren(const Particle & p,map<long,int> & nRes, int &ncount) {
-      foreach(const Particle &child, p.children()) {
+      for(const Particle &child : p.children()) {
 	if(child.children().empty()) {
-	  nRes[child.pdgId()]-=1;
+	  nRes[child.pid()]-=1;
 	  --ncount;
 	}
 	else
 	  findChildren(child,nRes,ncount);
       }
     }
 
     /// Perform the per-event analysis
     void analyze(const Event& event) {
       const FinalState& fs = apply<FinalState>(event, "FS");
       // total hadronic and muonic cross sections
       map<long,int> nCount;
       int ntotal(0);
-      foreach (const Particle& p, fs.particles()) {
-	nCount[p.pdgId()] += 1;
+      for (const Particle& p : fs.particles()) {
+	nCount[p.pid()] += 1;
 	++ntotal;
       }
       // mu+mu- + photons
       if(nCount[-13]==1 and nCount[13]==1 &&
 	 ntotal==2+nCount[22])
 	vetoEvent;
       // unstable charm analysis
       const FinalState& ufs = apply<UnstableParticles>(event, "UFS");
       for(unsigned int ix=0;ix<ufs.particles().size();++ix) {
        	const Particle& p1 = ufs.particles()[ix];
-       	int id1 = abs(p1.pdgId());
+       	int id1 = abs(p1.pid());
        	if(id1 != 411 && id1 != 413) continue;
       	// check fs
       	bool fs = true;
-      	foreach(const Particle & child, p1.children()) {
-      	  if(child.pdgId()==p1.pdgId()) {
+      	for (const Particle & child : p1.children()) {
+      	  if(child.pid()==p1.pid()) {
       	    fs = false;
       	    break;
       	  }
       	}
       	if(!fs) continue;
       	// find the children
       	map<long,int> nRes = nCount;
       	int ncount = ntotal;
       	findChildren(p1,nRes,ncount);
       	bool matched=false;
-       	int sign = p1.pdgId()/id1;
+       	int sign = p1.pid()/id1;
       	// loop over the other fs particles
       	for(unsigned int iy=ix+1;iy<ufs.particles().size();++iy) {
       	  const Particle& p2 = ufs.particles()[iy];
       	  fs = true;
-      	  foreach(const Particle & child, p2.children()) {
-      	    if(child.pdgId()==p2.pdgId()) {
+      	  for (const Particle & child : p2.children()) {
+      	    if(child.pid()==p2.pid()) {
       	      fs = false;
       	      break;
       	    }
       	  }
       	  if(!fs) continue;
-       	  if(p2.pdgId()/abs(p2.pdgId())==sign) continue;
-      	  int id2 = abs(p2.pdgId());
+       	  if(p2.pid()/abs(p2.pid())==sign) continue;
+      	  int id2 = abs(p2.pid());
        	  if(id2 != 411 && id2 != 413) continue;
-      	  if(!p2.parents().empty() && p2.parents()[0].pdgId()==p1.pdgId())
+      	  if(!p2.parents().empty() && p2.parents()[0].pid()==p1.pid())
       	    continue;
       	  map<long,int> nRes2 = nRes;
       	  int ncount2 = ncount;
       	  findChildren(p2,nRes2,ncount2);
 	  if(ncount2!=0) continue;
 	  matched=true;
 	  for(auto const & val : nRes2) {
 	    if(val.second!=0) {
 	      matched = false;
 	      break;
 	    }
 	  }
 	  if(matched) {
 	    if(id1==413 && id2==413) {
-	      _c_DpSDmS->fill(event.weight());
+	      _c_DpSDmS->fill();
 	    }
 	    else if((id1==411 && id2==413) ||
 		    (id1==413 && id2==411)) {
-	      _c_DpDmS->fill(event.weight());
+	      _c_DpDmS->fill();
 	    }
 	    break;
 	  }
       	}
 	if(matched) break;
       }
     }
 
 
     /// Normalise histograms etc., after the run
     void finalize() {
       double fact = crossSection()/ sumOfWeights()/nanobarn;
       for(unsigned int iy=1;iy<3;++iy) {
 	double sigma,error;
 	if(iy==1) {
 	  sigma = _c_DpDmS->val()*fact;
 	  error = _c_DpDmS->err()*fact;
 	}
 	else if(iy==2) {
 	  sigma = _c_DpSDmS->val()*fact;
 	  error = _c_DpSDmS->err()*fact;
 	}
 	Scatter2D temphisto(refData(1, 1, iy));
-        Scatter2DPtr     mult = bookScatter2D(1,1,iy);
+        Scatter2DPtr     mult;
+        book(mult, 1, 1, iy);
         for (size_t b = 0; b < temphisto.numPoints(); b++) {
           const double x  = temphisto.point(b).x();
           pair<double,double> ex = temphisto.point(b).xErrs();
           pair<double,double> ex2 = ex;
           if(ex2.first ==0.) ex2. first=0.0001;
           if(ex2.second==0.) ex2.second=0.0001;
           if (inRange(sqrtS()/GeV, x-ex2.first, x+ex2.second)) {
             mult   ->addPoint(x, sigma, ex, make_pair(error,error));
           }
           else {
             mult   ->addPoint(x, 0., ex, make_pair(0.,.0));
           }
         }
       }
     }
     //@}
 
 
     /// @name Histograms
     //@{
     CounterPtr _c_DpDmS, _c_DpSDmS;
     //@}
 
 
   };
 
 
   // The hook for the plugin system
   DECLARE_RIVET_PLUGIN(BELLE_2017_I1613517);
 
 
 }
diff --git a/analyses/pluginBES/BESIII_2014_I1286898.cc b/analyses/pluginBES/BESIII_2014_I1286898.cc
--- a/analyses/pluginBES/BESIII_2014_I1286898.cc
+++ b/analyses/pluginBES/BESIII_2014_I1286898.cc
@@ -1,81 +1,82 @@
 // -*- C++ -*-
 #include "Rivet/Analysis.hh"
 #include "Rivet/Projections/FinalState.hh"
 
 namespace Rivet {
 
 
   /// @brief Add a short analysis description here
   class BESIII_2014_I1286898 : public Analysis {
   public:
 
     /// Constructor
     DEFAULT_RIVET_ANALYSIS_CTOR(BESIII_2014_I1286898);
 
 
     /// @name Analysis methods
     //@{
 
     /// Book histograms and initialise projections before the run
     void init() {
 
       // Initialise and register projections
       declare(FinalState(), "FS");
 
       // Book histograms
-      _nproton = bookCounter("TMP/proton");
+      book(_nproton, "TMP/proton");
 
     }
 
 
     /// Perform the per-event analysis
     void analyze(const Event& event) {
       const FinalState& fs = apply<FinalState>(event, "FS");
       if(fs.particles().size()!=2) vetoEvent;
-      foreach (const Particle& p, fs.particles()) {
-	if(abs(p.pdgId())!=PID::PROTON) vetoEvent;
+      for (const Particle& p : fs.particles()) {
+	if(abs(p.pid())!=PID::PROTON) vetoEvent;
       }
-      _nproton->fill(event.weight());
+      _nproton->fill();
     }
 
 
     /// Normalise histograms etc., after the run
     void finalize() {
       double sigma = _nproton->val();
       double error = _nproton->err();
       sigma *= crossSection()/ sumOfWeights() /picobarn;
       error *= crossSection()/ sumOfWeights() /picobarn; 
       Scatter2D temphisto(refData(1, 1, 6));
-      Scatter2DPtr  mult = bookScatter2D(1, 1, 6);
+      Scatter2DPtr  mult;
+      book(mult, 1, 1, 6);
       for (size_t b = 0; b < temphisto.numPoints(); b++) {
 	const double x  = temphisto.point(b).x();
 	pair<double,double> ex = temphisto.point(b).xErrs();
 	pair<double,double> ex2 = ex;
 	if(ex2.first ==0.) ex2. first=0.0001;
 	if(ex2.second==0.) ex2.second=0.0001;
 	if (inRange(sqrtS()/GeV, x-ex2.first, x+ex2.second)) {
 	  mult->addPoint(x, sigma, ex, make_pair(error,error));
 	}
 	else {
 	  mult->addPoint(x, 0., ex, make_pair(0.,.0));
 	}
       }
     }
 
     //@}
 
 
     /// @name Histograms
     //@{
     CounterPtr _nproton;
     //@}
 
 
   };
 
 
   // The hook for the plugin system
   DECLARE_RIVET_PLUGIN(BESIII_2014_I1286898);
 
 
 }
diff --git a/analyses/pluginBES/BESIII_2015_I1355215.cc b/analyses/pluginBES/BESIII_2015_I1355215.cc
--- a/analyses/pluginBES/BESIII_2015_I1355215.cc
+++ b/analyses/pluginBES/BESIII_2015_I1355215.cc
@@ -1,121 +1,122 @@
 // -*- C++ -*-
 #include "Rivet/Analysis.hh"
 #include "Rivet/Projections/FinalState.hh"
 #include "Rivet/Projections/UnstableParticles.hh"
 
 namespace Rivet {
 
 
   /// @brief Add a short analysis description here
   class BESIII_2015_I1355215 : public Analysis {
   public:
 
     /// Constructor
     DEFAULT_RIVET_ANALYSIS_CTOR(BESIII_2015_I1355215);
 
 
     /// @name Analysis methods
     //@{
 
     /// Book histograms and initialise projections before the run
     void init() {
       declare(FinalState(), "FS");
       declare(UnstableParticles(), "UFS");
-      _nJPsi = bookCounter("TMP/jpsi");
+      book(_nJPsi, "TMP/jpsi");
     }
 
     void findChildren(const Particle & p,map<long,int> & nRes, int &ncount) {
-      foreach(const Particle &child, p.children()) {
+      for (const Particle &child : p.children()) {
 	if(child.children().empty()) {
-	  --nRes[child.pdgId()];
+	  --nRes[child.pid()];
 	  --ncount;
 	}
 	else
 	  findChildren(child,nRes,ncount);
       }
     }
 
     /// Perform the per-event analysis
     void analyze(const Event& event) {
       const FinalState& fs = apply<FinalState>(event, "FS");
       map<long,int> nCount;
       int ntotal(0);
-      foreach (const Particle& p, fs.particles()) {
-	nCount[p.pdgId()] += 1;
+      for (const Particle& p : fs.particles()) {
+	nCount[p.pid()] += 1;
 	++ntotal;
       }
       const FinalState& ufs = apply<FinalState>(event, "UFS");
-      foreach (const Particle& p1, ufs.particles()) {
+      for (const Particle& p1 : ufs.particles()) {
 	if(p1.children().empty()) continue;
 	bool matched=false;
 	// find the j/psi
-	if(p1.pdgId()!=443) continue;
+	if(p1.pid()!=443) continue;
 	map<long,int> nRes = nCount;
 	int ncount = ntotal;
 	findChildren(p1,nRes,ncount);
 	
-	foreach (const Particle& p2, ufs.particles()) {
+	for (const Particle& p2 : ufs.particles()) {
 	  if(p2.children().empty()) continue;
 	  // find the j/psi
-	  if(p2.pdgId()!=331) continue;
+	  if(p2.pid()!=331) continue;
 	  map<long,int> nRes2 = nRes;
 	  int ncount2 = ncount;
 	  findChildren(p2,nRes2,ncount2);
 	  if(ncount2!=0) continue;
 	  matched=true;
 	  for(auto const & val : nRes2) {
 	    if(val.second!=0) {
 	      matched = false;
 	      break;
 	    }
 	  }
 	  if(matched) {
-	    _nJPsi->fill(event.weight());
+	    _nJPsi->fill();
 	    break;
 	  }
 	}
 	if(matched) break;
       }
     }
 
 
     /// Normalise histograms etc., after the run
     void finalize() {
 
       double sigma = _nJPsi->val();
       double error = _nJPsi->err();
       sigma *= crossSection()/ sumOfWeights() /picobarn;
       error *= crossSection()/ sumOfWeights() /picobarn; 
       Scatter2D temphisto(refData(1, 1, 10));
-      Scatter2DPtr  mult = bookScatter2D(1, 1, 10);
+      Scatter2DPtr  mult;
+      book(mult, 1, 1, 10);
       for (size_t b = 0; b < temphisto.numPoints(); b++) {
 	const double x  = temphisto.point(b).x();
 	pair<double,double> ex = temphisto.point(b).xErrs();
 	pair<double,double> ex2 = ex;
 	if(ex2.first ==0.) ex2. first=0.0001;
 	if(ex2.second==0.) ex2.second=0.0001;
 	if (inRange(sqrtS()/GeV, x-ex2.first, x+ex2.second)) {
 	  mult->addPoint(x, sigma, ex, make_pair(error,error));
 	}
 	else {
 	  mult->addPoint(x, 0., ex, make_pair(0.,.0));
 	}
       }
     }
 
     //@}
 
 
     /// @name Histograms
     //@{
     CounterPtr _nJPsi;
     //@}
 
   };
 
 
   // The hook for the plugin system
   DECLARE_RIVET_PLUGIN(BESIII_2015_I1355215);
 
 
 }
diff --git a/analyses/pluginBES/BESIII_2015_I1358937.cc b/analyses/pluginBES/BESIII_2015_I1358937.cc
--- a/analyses/pluginBES/BESIII_2015_I1358937.cc
+++ b/analyses/pluginBES/BESIII_2015_I1358937.cc
@@ -1,82 +1,83 @@
 // -*- C++ -*-
 #include "Rivet/Analysis.hh"
 #include "Rivet/Projections/FinalState.hh"
 
 
 namespace Rivet {
 
 
   /// @brief Add a short analysis description here
   class BESIII_2015_I1358937 : public Analysis {
   public:
 
     /// Constructor
     DEFAULT_RIVET_ANALYSIS_CTOR(BESIII_2015_I1358937);
 
 
     /// @name Analysis methods
     //@{
 
     /// Book histograms and initialise projections before the run
     void init() {
 
       // Initialise and register projections
       declare(FinalState(), "FS");
 
       // Book histograms
-      _nproton = bookCounter("TMP/proton");
+      book(_nproton, "TMP/proton");
 
     }
 
 
     /// Perform the per-event analysis
     void analyze(const Event& event) {
       const FinalState& fs = apply<FinalState>(event, "FS");
       if(fs.particles().size()!=2) vetoEvent;
-      foreach (const Particle& p, fs.particles()) {
-	if(abs(p.pdgId())!=PID::PROTON) vetoEvent;
+      for (const Particle& p : fs.particles()) {
+	if(abs(p.pid())!=PID::PROTON) vetoEvent;
       }
-      _nproton->fill(event.weight());
+      _nproton->fill();
     }
 
 
     /// Normalise histograms etc., after the run
     void finalize() {
       double sigma = _nproton->val();
       double error = _nproton->err();
       sigma *= crossSection()/ sumOfWeights() /picobarn;
       error *= crossSection()/ sumOfWeights() /picobarn; 
       Scatter2D temphisto(refData(1, 1, 5));
-      Scatter2DPtr  mult = bookScatter2D(1, 1, 5);
+      Scatter2DPtr  mult;
+      book(mult, 1, 1, 5);
       for (size_t b = 0; b < temphisto.numPoints(); b++) {
 	const double x  = temphisto.point(b).x();
 	pair<double,double> ex = temphisto.point(b).xErrs();
 	pair<double,double> ex2 = ex;
 	if(ex2.first ==0.) ex2. first=0.0001;
 	if(ex2.second==0.) ex2.second=0.0001;
 	if (inRange(sqrtS()/GeV, x-ex2.first, x+ex2.second)) {
 	  mult->addPoint(x, sigma, ex, make_pair(error,error));
 	}
 	else {
 	  mult->addPoint(x, 0., ex, make_pair(0.,.0));
 	}
       }
     }
 
     //@}
 
 
     /// @name Histograms
     //@{
     CounterPtr _nproton;
     //@}
 
 
   };
 
 
   // The hook for the plugin system
   DECLARE_RIVET_PLUGIN(BESIII_2015_I1358937);
 
 
 }
diff --git a/analyses/pluginBES/BESIII_2015_I1364494.cc b/analyses/pluginBES/BESIII_2015_I1364494.cc
--- a/analyses/pluginBES/BESIII_2015_I1364494.cc
+++ b/analyses/pluginBES/BESIII_2015_I1364494.cc
@@ -1,99 +1,99 @@
 // -*- C++ -*-
 #include "Rivet/Analysis.hh"
 #include "Rivet/Projections/UnstableParticles.hh"
 
 namespace Rivet {
 
 
   /// @brief Add a short analysis description here
   class BESIII_2015_I1364494 : public Analysis {
   public:
 
     /// Constructor
     DEFAULT_RIVET_ANALYSIS_CTOR(BESIII_2015_I1364494);
 
 
     /// @name Analysis methods
     //@{
 
     /// Book histograms and initialise projections before the run
     void init() {
 
       // Initialise and register projections
       declare(UnstableParticles(), "UFS");
 
       // Book histograms
-      _h_m = bookHisto1D(1, 1, 3);
-      _netap = 0.;
+      book(_h_m, 1, 1, 3);
+      book(_netap, "TMP/netap");
     }
     
     void findDecayProducts(const Particle & mother, unsigned int & nstable, unsigned int & ngamma, 
                            unsigned int & nep, unsigned int & nem, FourMomentum & ptot) {
       for(const Particle & p : mother.children()) {
-        int id = p.pdgId();
+        int id = p.pid();
         if (id == PID::EMINUS ) {
 	  ++nem;
           ++nstable;
 	  ptot += p.momentum();
 	}
         else if (id == PID::EPLUS) {
           ++nep;
           ++nstable;
 	  ptot += p.momentum();
         }
         else if ( !p.children().empty() ) {
           findDecayProducts(p, nstable, ngamma,nep,nem,ptot);
         }
         else if (id == PID::GAMMA) {
 	  ++ngamma;
           ++nstable;
         }
         else
           ++nstable;
       }
     }
 
 
     /// Perform the per-event analysis
     void analyze(const Event& event) {
 
       // Loop over eta' mesons
-      foreach(const Particle& p, apply<UnstableParticles>(event, "UFS").particles(Cuts::pid==331)) {
+      for (const Particle& p : apply<UnstableParticles>(event, "UFS").particles(Cuts::pid==331)) {
 	unsigned nstable(0),ngamma(0),nep(0),nem(0);
 	FourMomentum ptot;
 	findDecayProducts(p,nstable,ngamma,nep,nem,ptot);
 	if(nstable==3 && nem==1 && nem==1 && ngamma==1)
-	  _h_m->fill(ptot.mass(),event.weight());
+	  _h_m->fill(ptot.mass());
 	else if(nstable==2 &&ngamma==2)
-	  _netap+=event.weight();
+	  _netap->fill();
       }
     }
 
 
     /// Normalise histograms etc., after the run
     void finalize() {
 
       // divide by no so BR and mult by bin width
       // and 100 as in %
-      scale(_h_m,1./_netap*0.1*100.);
+      scale(_h_m,1./_netap->sumW()*0.1*100.);
 
     }
 
     //@}
 
 
     /// @name Histograms
     //@{
     Histo1DPtr _h_m;
-    double _netap;
+    CounterPtr _netap;
     //@}
 
 
   };
 
 
   // The hook for the plugin system
   DECLARE_RIVET_PLUGIN(BESIII_2015_I1364494);
 
 
 }
diff --git a/analyses/pluginBES/BESIII_2015_I1377204.cc b/analyses/pluginBES/BESIII_2015_I1377204.cc
--- a/analyses/pluginBES/BESIII_2015_I1377204.cc
+++ b/analyses/pluginBES/BESIII_2015_I1377204.cc
@@ -1,119 +1,120 @@
 // -*- C++ -*-
 #include "Rivet/Analysis.hh"
 #include "Rivet/Projections/FinalState.hh"
 #include "Rivet/Projections/UnstableParticles.hh"
 
 namespace Rivet {
 
 
   /// @brief Add a short analysis description here
   class BESIII_2015_I1377204 : public Analysis {
   public:
 
     /// Constructor
     DEFAULT_RIVET_ANALYSIS_CTOR(BESIII_2015_I1377204);
 
 
     /// @name Analysis methods
     //@{
 
     /// Book histograms and initialise projections before the run
     void init() {
       declare(FinalState(), "FS");
       declare(UnstableParticles(), "UFS");
-      _nJPsi = bookCounter("TMP/jpsi");
+      book(_nJPsi, "TMP/jpsi");
     }
 
 
     void findChildren(const Particle & p,map<long,int> & nRes, int &ncount) {
-      foreach(const Particle &child, p.children()) {
+      for (const Particle &child : p.children()) {
 	if(child.children().empty()) {
-	  --nRes[child.pdgId()];
+	  --nRes[child.pid()];
 	  --ncount;
 	}
 	else
 	  findChildren(child,nRes,ncount);
       }
     }
 
     /// Perform the per-event analysis
     void analyze(const Event& event) {
       const FinalState& fs = apply<FinalState>(event, "FS");
       map<long,int> nCount;
       int ntotal(0);
-      foreach (const Particle& p, fs.particles()) {
-	nCount[p.pdgId()] += 1;
+      for (const Particle& p : fs.particles()) {
+	nCount[p.pid()] += 1;
 	++ntotal;
       }
       const FinalState& ufs = apply<FinalState>(event, "UFS");
-      foreach (const Particle& p, ufs.particles()) {
+      for (const Particle& p : ufs.particles()) {
 	if(p.children().empty()) continue;
 	// find the j/psi
-	if(p.pdgId()==443) {
+	if(p.pid()==443) {
 	  map<long,int> nRes = nCount;
 	  int ncount = ntotal;
 	  findChildren(p,nRes,ncount);
 	  // J/psi pi0pi0
 	  if(ncount!=2) continue;
 	  bool matched = true;
 	  for(auto const & val : nRes) {
 	    if(abs(val.first)==111) {
 	      if(val.second !=2) {
 		matched = false;
 		break;
 	      }
 	    }
 	    else if(val.second!=0) {
 	      matched = false;
 	      break;
 	    }
 	  }
 	  if(matched) {
-	    _nJPsi->fill(event.weight());
+	    _nJPsi->fill();
 	    break;
 	  }
 	}
       }
     }
 
 
     /// Normalise histograms etc., after the run
     void finalize() {
       double sigma = _nJPsi->val();
       double error = _nJPsi->err();
       sigma *= crossSection()/ sumOfWeights() /picobarn;
       error *= crossSection()/ sumOfWeights() /picobarn; 
       Scatter2D temphisto(refData(1, 1, 12));
-      Scatter2DPtr  mult = bookScatter2D(1, 1, 12);
+      Scatter2DPtr  mult;
+      book(mult, 1, 1, 12);
       for (size_t b = 0; b < temphisto.numPoints(); b++) {
 	const double x  = temphisto.point(b).x();
 	pair<double,double> ex = temphisto.point(b).xErrs();
 	pair<double,double> ex2 = ex;
 	if(ex2.first ==0.) ex2. first=0.0001;
 	if(ex2.second==0.) ex2.second=0.0001;
 	if (inRange(sqrtS()/GeV, x-ex2.first, x+ex2.second)) {
 	  mult->addPoint(x, sigma, ex, make_pair(error,error));
 	}
 	else {
 	  mult->addPoint(x, 0., ex, make_pair(0.,.0));
 	}
       }
     }
 
     //@}
 
 
     /// @name Histograms
     //@{
     CounterPtr _nJPsi;
     //@}
 
 
   };
 
 
   // The hook for the plugin system
   DECLARE_RIVET_PLUGIN(BESIII_2015_I1377204);
 
 
 }
diff --git a/analyses/pluginBES/BESIII_2015_I1391138.cc b/analyses/pluginBES/BESIII_2015_I1391138.cc
--- a/analyses/pluginBES/BESIII_2015_I1391138.cc
+++ b/analyses/pluginBES/BESIII_2015_I1391138.cc
@@ -1,85 +1,85 @@
 // -*- C++ -*-
 #include "Rivet/Analysis.hh"
 #include "Rivet/Projections/UnstableParticles.hh"
 
 namespace Rivet {
 
 
   /// @brief Based on BABAR_2015_I1334693
   class BESIII_2015_I1391138 : public Analysis {
   public:
 
     /// Constructor
     DEFAULT_RIVET_ANALYSIS_CTOR(BESIII_2015_I1391138);
 
 
     /// @name Analysis methods
     //@{
 
     /// Book histograms and initialise projections before the run
     void init() {
 
       // Initialise and register projections
       declare(UnstableParticles(), "UFS");
 
       // Book histograms
-      _h_q2_K  = bookHisto1D(1, 1, 3);
-      _h_q2_pi = bookHisto1D(2, 1, 3);
-      nD0 = 0.;
+      book(_h_q2_K, 1, 1, 3);
+      book(_h_q2_pi, 2, 1, 3);
+      book(nD0, "TMP/DCounter");
     }
 
     // Calculate the Q2 using mother and daugher meson
     double q2(const Particle& B, int mesonID) {
       FourMomentum q = B.mom() - filter_select(B.children(), Cuts::pid==mesonID)[0];
       return q*q;
     }
     
     // Check for explicit decay into pdgids
     bool isSemileptonicDecay(const Particle& mother, vector<int> ids) {
       // Trivial check to ignore any other decays but the one in question modulo photons
       const Particles children = mother.children(Cuts::pid!=PID::PHOTON);
       if (children.size()!=ids.size()) return false;
       // Check for the explicit decay
       return all(ids, [&](int i){return count(children, hasPID(i))==1;});
     }
 
     /// Perform the per-event analysis
     void analyze(const Event& event) {
 
       // Loop over D0 mesons
-      foreach(const Particle& p, apply<UnstableParticles>(event, "UFS").particles(Cuts::pid==PID::D0)) {
-	nD0 += event.weight();
+      for (const Particle& p : apply<UnstableParticles>(event, "UFS").particles(Cuts::pid==PID::D0)) {
+	nD0->fill();
         if (isSemileptonicDecay(p, {PID::PIMINUS, PID::POSITRON, PID::NU_E})) {
-          _h_q2_pi->fill(q2(p, PID::PIMINUS), event.weight());
+          _h_q2_pi->fill(q2(p, PID::PIMINUS));
         }
 	else if(isSemileptonicDecay(p, {PID::KMINUS, PID::POSITRON, PID::NU_E})) {
-          _h_q2_K ->fill(q2(p, PID::KMINUS), event.weight());
+          _h_q2_K ->fill(q2(p, PID::KMINUS));
         }
       }
     }
 
     /// Normalise histograms etc., after the run
     void finalize() {
       // scale by D0 lifetime = 410.1e-6 ps (from PDG 2014 used in paper)
       // and bin width 0.1 K and 0.2 pi
-      scale(_h_q2_K , 1./nD0/410.1e-6*0.1);
-      scale(_h_q2_pi, 1./nD0/410.1e-6*0.2);
+      scale(_h_q2_K , 1./nD0->sumW()/410.1e-6*0.1);
+      scale(_h_q2_pi, 1./nD0->sumW()/410.1e-6*0.2);
     }
     //@}
 
 
     /// @name Histograms
     //@{
     Histo1DPtr _h_q2_K,_h_q2_pi;
-    double nD0;
+    CounterPtr nD0;
     //@}
 
 
   };
 
 
   // The hook for the plugin system
   DECLARE_RIVET_PLUGIN(BESIII_2015_I1391138);
 
 
 }
diff --git a/analyses/pluginBES/BESIII_2016_I1385603.cc b/analyses/pluginBES/BESIII_2016_I1385603.cc
--- a/analyses/pluginBES/BESIII_2016_I1385603.cc
+++ b/analyses/pluginBES/BESIII_2016_I1385603.cc
@@ -1,82 +1,83 @@
 // -*- C++ -*-
 #include "Rivet/Analysis.hh"
 #include "Rivet/Projections/FinalState.hh"
 
 
 namespace Rivet {
 
 
   /// @brief Add a short analysis description here
   class BESIII_2016_I1385603 : public Analysis {
   public:
 
     /// Constructor
     DEFAULT_RIVET_ANALYSIS_CTOR(BESIII_2016_I1385603);
 
 
     /// @name Analysis methods
     //@{
 
     /// Book histograms and initialise projections before the run
     void init() {
 
       // Initialise and register projections
       declare(FinalState(), "FS");
 
       // Book histograms
-      _npion = bookCounter("TMP/pion");
+      book(_npion, "TMP/pion");
 
     }
 
 
     /// Perform the per-event analysis
     void analyze(const Event& event) {
       const FinalState& fs = apply<FinalState>(event, "FS");
       if(fs.particles().size()!=2) vetoEvent;
-      foreach (const Particle& p, fs.particles()) {
-	if(abs(p.pdgId())!=PID::PIPLUS) vetoEvent;
+      for (const Particle& p : fs.particles()) {
+	if(abs(p.pid())!=PID::PIPLUS) vetoEvent;
       }
-      _npion->fill(event.weight());
+      _npion->fill();
     }
 
 
     /// Normalise histograms etc., after the run
     void finalize() {
       double sigma = _npion->val();
       double error = _npion->err();
       sigma *= crossSection()/ sumOfWeights() /nanobarn;
       error *= crossSection()/ sumOfWeights() /nanobarn;
       Scatter2D temphisto(refData(1, 1, 1));
-      Scatter2DPtr  mult = bookScatter2D(1, 1, 1);
+      Scatter2DPtr  mult;
+      book(mult, 1, 1, 1);
       for (size_t b = 0; b < temphisto.numPoints(); b++) {
 	const double x  = temphisto.point(b).x();
 	pair<double,double> ex = temphisto.point(b).xErrs();
 	pair<double,double> ex2 = ex;
 	if(ex2.first ==0.) ex2. first=0.0001;
 	if(ex2.second==0.) ex2.second=0.0001;
 	if (inRange(sqrtS()/MeV, x-ex2.first, x+ex2.second)) {
 	  mult->addPoint(x, sigma, ex, make_pair(error,error));
 	}
 	else {
 	  mult->addPoint(x, 0., ex, make_pair(0.,.0));
 	}
       } 
     }
 
     //@}
 
 
     /// @name Histograms
     //@{
     CounterPtr _npion;
     //@}
 
 
   };
 
 
   // The hook for the plugin system
   DECLARE_RIVET_PLUGIN(BESIII_2016_I1385603);
 
 
 }
diff --git a/analyses/pluginBES/BESIII_2016_I1457597.cc b/analyses/pluginBES/BESIII_2016_I1457597.cc
--- a/analyses/pluginBES/BESIII_2016_I1457597.cc
+++ b/analyses/pluginBES/BESIII_2016_I1457597.cc
@@ -1,120 +1,121 @@
 // -*- C++ -*-
 #include "Rivet/Analysis.hh"
 #include "Rivet/Projections/FinalState.hh"
 #include "Rivet/Projections/UnstableParticles.hh"
 
 namespace Rivet {
 
 
   /// @brief Add a short analysis description here
   class BESIII_2016_I1457597 : public Analysis {
   public:
 
     /// Constructor
     DEFAULT_RIVET_ANALYSIS_CTOR(BESIII_2016_I1457597);
 
 
     /// @name Analysis methods
     //@{
 
     /// Book histograms and initialise projections before the run
     void init() {
       declare(FinalState(), "FS");
       declare(UnstableParticles(), "UFS");
-      _nJPsi = bookCounter("TMP/jpsi");
+      book(_nJPsi, "TMP/jpsi");
     }
 
     void findChildren(const Particle & p,map<long,int> & nRes, int &ncount) {
-      foreach(const Particle &child, p.children()) {
+      for(const Particle &child : p.children()) {
 	if(child.children().empty()) {
-	  --nRes[child.pdgId()];
+	  --nRes[child.pid()];
 	  --ncount;
 	}
 	else
 	  findChildren(child,nRes,ncount);
       }
     }
 
     /// Perform the per-event analysis
     void analyze(const Event& event) {
       const FinalState& fs = apply<FinalState>(event, "FS");
       map<long,int> nCount;
       int ntotal(0);
-      foreach (const Particle& p, fs.particles()) {
-	nCount[p.pdgId()] += 1;
+      for (const Particle& p : fs.particles()) {
+	nCount[p.pid()] += 1;
 	++ntotal;
       }
       const FinalState& ufs = apply<FinalState>(event, "UFS");
-      foreach (const Particle& p1, ufs.particles()) {
+      for (const Particle& p1 : ufs.particles()) {
 	bool matched=false;
 	if(p1.children().empty()) continue;
 	// find the j/psi
-	if(p1.pdgId()!=443) continue;
+	if(p1.pid()!=443) continue;
 	map<long,int> nRes = nCount;
 	int ncount = ntotal;
 	findChildren(p1,nRes,ncount);
 	
-	foreach (const Particle& p2, ufs.particles()) {
+	for (const Particle& p2 : ufs.particles()) {
 	  if(p2.children().empty()) continue;
 	  // find the j/psi
-	  if(p2.pdgId()!=331) continue;
+	  if(p2.pid()!=331) continue;
 	  map<long,int> nRes2 = nRes;
 	  int ncount2 = ncount;
 	  findChildren(p2,nRes2,ncount2);
 	  if(ncount2!=0) continue;
 	  matched=true;
 	  for(auto const & val : nRes2) {
 	    if(val.second!=0) {
 	      matched = false;
 	      break;
 	    }
 	  }
 	  if(matched) {
-	    _nJPsi->fill(event.weight());
+	    _nJPsi->fill();
 	    break;
 	  }
 	}
 	if(matched) break;
       }
     }
 
     /// Normalise histograms etc., after the run
     void finalize() {
       double sigma = _nJPsi->val();
       double error = _nJPsi->err();
       sigma *= crossSection()/ sumOfWeights() /picobarn;
       error *= crossSection()/ sumOfWeights() /picobarn; 
       Scatter2D temphisto(refData(1, 1, 7));
-      Scatter2DPtr  mult = bookScatter2D(1, 1, 7);
+      Scatter2DPtr  mult;
+      book(mult, 1, 1, 7);
       for (size_t b = 0; b < temphisto.numPoints(); b++) {
 	const double x  = temphisto.point(b).x();
 	pair<double,double> ex = temphisto.point(b).xErrs();
 	pair<double,double> ex2 = ex;
 	if(ex2.first ==0.) ex2. first=0.0001;
 	if(ex2.second==0.) ex2.second=0.0001;
 	if (inRange(sqrtS()/GeV, x-ex2.first, x+ex2.second)) {
 	  mult->addPoint(x, sigma, ex, make_pair(error,error));
 	}
 	else {
 	  mult->addPoint(x, 0., ex, make_pair(0.,.0));
 	}
       }
     }
 
     //@}
 
 
     /// @name Histograms
     //@{
     CounterPtr _nJPsi;
     //@}
 
 
   };
 
 
   // The hook for the plugin system
   DECLARE_RIVET_PLUGIN(BESIII_2016_I1457597);
 
 
 }
diff --git a/analyses/pluginBES/BESIII_2016_I1495838.cc b/analyses/pluginBES/BESIII_2016_I1495838.cc
--- a/analyses/pluginBES/BESIII_2016_I1495838.cc
+++ b/analyses/pluginBES/BESIII_2016_I1495838.cc
@@ -1,119 +1,120 @@
 // -*- C++ -*-
 #include "Rivet/Analysis.hh"
 #include "Rivet/Projections/FinalState.hh"
 #include "Rivet/Projections/UnstableParticles.hh"
 
 namespace Rivet {
 
 
   /// @brief Add a short analysis description here
   class BESIII_2016_I1495838 : public Analysis {
   public:
 
     /// Constructor
     DEFAULT_RIVET_ANALYSIS_CTOR(BESIII_2016_I1495838);
 
 
     /// @name Analysis methods
     //@{
 
     /// Book histograms and initialise projections before the run
     void init() {
       declare(FinalState(), "FS");
       declare(UnstableParticles(), "UFS");
-      _nPsi = bookCounter("TMP/psi");
+      book(_nPsi, "TMP/psi");
     }
 
     void findChildren(const Particle & p,map<long,int> & nRes, int &ncount) {
-      foreach(const Particle &child, p.children()) {
+      for (const Particle &child : p.children()) {
 	if(child.children().empty()) {
-	  --nRes[child.pdgId()];
+	  --nRes[child.pid()];
 	  --ncount;
 	}
 	else
 	  findChildren(child,nRes,ncount);
       }
     }
 
     /// Perform the per-event analysis
     void analyze(const Event& event) {
       const FinalState& fs = apply<FinalState>(event, "FS");
       map<long,int> nCount;
       int ntotal(0);
-      foreach (const Particle& p, fs.particles()) {
-	nCount[p.pdgId()] += 1;
+      for (const Particle& p: fs.particles()) {
+	nCount[p.pid()] += 1;
 	++ntotal;
       }
       const FinalState& ufs = apply<FinalState>(event, "UFS");
-      foreach (const Particle& p, ufs.particles()) {
+      for (const Particle& p : ufs.particles()) {
 	if(p.children().empty()) continue;
 	// find the psi
-	if(p.pdgId()==443) {
+	if(p.pid()==443) {
 	  map<long,int> nRes = nCount;
 	  int ncount = ntotal;
 	  findChildren(p,nRes,ncount);
 	  // psi pi+pi-
 	  if(ncount!=2) continue;
 	  bool matched = true;
 	  for(auto const & val : nRes) {
 	    if(abs(val.first)==211) {
 	      if(val.second !=1) {
 		matched = false;
 		break;
 	      }
 	    }
 	    else if(val.second!=0) {
 	      matched = false;
 	      break;
 	    }
 	  }
 	  if(matched) {
-	    _nPsi->fill(event.weight());
+	    _nPsi->fill();
 	    break;
 	  }
 	}
       }
     }
 
 
     /// Normalise histograms etc., after the run
     void finalize() {
       double fact =  crossSection()/ sumOfWeights() /picobarn;
       double sigma = _nPsi->val()*fact;
       double error = _nPsi->err()*fact;
       for(unsigned int ix=1;ix<3;++ix) {
 	Scatter2D temphisto(refData(ix, 1, 1));
-	Scatter2DPtr  mult = bookScatter2D(ix, 1, 1);
+	Scatter2DPtr  mult;
+        book(mult, ix, 1, 1);
 	for (size_t b = 0; b < temphisto.numPoints(); b++) {
 	  const double x  = temphisto.point(b).x();
 	  pair<double,double> ex = temphisto.point(b).xErrs();
 	  pair<double,double> ex2 = ex;
 	  if(ex2.first ==0.) ex2. first=0.0001;
 	  if(ex2.second==0.) ex2.second=0.0001;
 	  if (inRange(sqrtS()/GeV, x-ex2.first, x+ex2.second)) {
 	    mult->addPoint(x, sigma, ex, make_pair(error,error));
 	  }
 	  else {
 	    mult->addPoint(x, 0., ex, make_pair(0.,.0));
 	  }
 	}
       }
     }
 
     //@}
 
 
     /// @name Histograms
     //@{
     CounterPtr _nPsi;
     //@}
 
 
   };
 
 
   // The hook for the plugin system
   DECLARE_RIVET_PLUGIN(BESIII_2016_I1495838);
 
 
 }
diff --git a/analyses/pluginBES/BESIII_2018_I1627871.cc b/analyses/pluginBES/BESIII_2018_I1627871.cc
--- a/analyses/pluginBES/BESIII_2018_I1627871.cc
+++ b/analyses/pluginBES/BESIII_2018_I1627871.cc
@@ -1,136 +1,137 @@
 // -*- C++ -*-
 #include "Rivet/Analysis.hh"
 #include "Rivet/Projections/FinalState.hh"
 #include "Rivet/Projections/UnstableParticles.hh"
 
 namespace Rivet {
 
 
   /// @brief Add a short analysis description here
   class BESIII_2018_I1627871 : public Analysis {
   public:
 
     /// Constructor
     DEFAULT_RIVET_ANALYSIS_CTOR(BESIII_2018_I1627871);
 
 
     /// @name Analysis methods
     //@{
 
     /// Book histograms and initialise projections before the run
     void init() {
       // Initialise and register projections
       declare(FinalState(), "FS");
       declare(UnstableParticles(), "UFS");
-      _nLambda= bookCounter( "/TMP/nLambda" );
+      book(_nLambda, "/TMP/nLambda" );
     }
 
     void findChildren(const Particle & p,map<long,int> & nRes, int &ncount) {
-      foreach(const Particle &child, p.children()) {
+      for (const Particle &child : p.children()) {
 	if(child.children().empty()) {
-	  nRes[child.pdgId()]-=1;
+	  nRes[child.pid()]-=1;
 	  --ncount;
 	}
 	else
 	  findChildren(child,nRes,ncount);
       }
     }
 
     /// Perform the per-event analysis
     void analyze(const Event& event) {
       const FinalState& fs = apply<FinalState>(event, "FS");
       // total hadronic and muonic cross sections
       map<long,int> nCount;
       int ntotal(0);
-      foreach (const Particle& p, fs.particles()) {
-	nCount[p.pdgId()] += 1;
+      for (const Particle& p : fs.particles()) {
+	nCount[p.pid()] += 1;
 	++ntotal;
       }
       // find the Lambdas
       const FinalState& ufs = apply<UnstableParticles>(event, "UFS");
       for(unsigned int ix=0;ix<ufs.particles().size();++ix) {
 	const Particle& p1 = ufs.particles()[ix];
-	if(abs(p1.pdgId())!=3122) continue;
+	if(abs(p1.pid())!=3122) continue;
 	bool matched = false;
 	// check fs
 	bool fs = true;
-	foreach(const Particle & child, p1.children()) {
-	  if(child.pdgId()==p1.pdgId()) {
+	for (const Particle & child : p1.children()) {
+	  if(child.pid()==p1.pid()) {
 	    fs = false;
 	    break;
 	  }
 	}
 	if(!fs) continue;
 	// find the children
 	map<long,int> nRes = nCount;
 	int ncount = ntotal;
 	findChildren(p1,nRes,ncount);
 	for(unsigned int iy=ix+1;iy<ufs.particles().size();++iy) {
 	  const Particle& p2 = ufs.particles()[iy];
-	  if(abs(p2.pdgId())!=3122) continue;
+	  if(abs(p2.pid())!=3122) continue;
 	  // check fs
 	  bool fs = true;
-	  foreach(const Particle & child, p2.children()) {
-	    if(child.pdgId()==p2.pdgId()) {
+	  for (const Particle & child : p2.children()) {
+	    if(child.pid()==p2.pid()) {
 	      fs = false;
 	      break;
 	    }
 	  }
 	  if(!fs) continue;
 	  map<long,int> nRes2 = nRes;
 	  int ncount2 = ncount;
 	  findChildren(p2,nRes2,ncount2);
 	  if(ncount2!=0) continue;
 	  matched=true;
 	  for(auto const & val : nRes2) {
 	    if(val.second!=0) {
 	      matched = false;
 	      break;
 	    }
 	  }
 	  if(matched) {
-	    _nLambda->fill(event.weight());
+	    _nLambda->fill();
 	    break;
 	  }
 	}
 	if(matched) break;
       }
     }
 
 
     /// Normalise histograms etc., after the run
     void finalize() {
       double sigma = _nLambda->val();
       double error = _nLambda->err();
       sigma *= crossSection()/ sumOfWeights() /picobarn;
       error *= crossSection()/ sumOfWeights() /picobarn; 
       Scatter2D temphisto(refData(1, 1, 1));
-      Scatter2DPtr  mult = bookScatter2D(1, 1, 1);
+      Scatter2DPtr  mult;
+      book(mult, 1, 1, 1);
       for (size_t b = 0; b < temphisto.numPoints(); b++) {
 	const double x  = temphisto.point(b).x();
 	pair<double,double> ex = temphisto.point(b).xErrs();
 	pair<double,double> ex2 = ex;
 	if(ex2.first ==0.) ex2. first=0.0001;
 	if(ex2.second==0.) ex2.second=0.0001;
 	if (inRange(sqrtS()/GeV, x-ex2.first, x+ex2.second)) {
 	  mult->addPoint(x, sigma, ex, make_pair(error,error));
 	}
 	else {
 	  mult->addPoint(x, 0., ex, make_pair(0.,.0));
 	}
       }
     }
     //@}
 
     /// @name Histograms
     //@{
     CounterPtr _nLambda;
     //@}
   };
 
 
   // The hook for the plugin system
   DECLARE_RIVET_PLUGIN(BESIII_2018_I1627871);
 
 
 }
diff --git a/analyses/pluginBES/BESIII_2018_I1691798.cc b/analyses/pluginBES/BESIII_2018_I1691798.cc
--- a/analyses/pluginBES/BESIII_2018_I1691798.cc
+++ b/analyses/pluginBES/BESIII_2018_I1691798.cc
@@ -1,84 +1,85 @@
 // -*- C++ -*-
 #include "Rivet/Analysis.hh"
 #include "Rivet/Projections/FinalState.hh"
 
 namespace Rivet {
 
 
   /// @brief Add a short analysis description here
   class BESIII_2018_I1691798 : public Analysis {
   public:
 
     /// Constructor
     DEFAULT_RIVET_ANALYSIS_CTOR(BESIII_2018_I1691798);
 
 
     /// @name Analysis methods
     //@{
 
     /// Book histograms and initialise projections before the run
     void init() {
       // Initialise and register projections
       declare(FinalState(), "FS");
-      _nKKpi= bookCounter( "/TMP/nKKpi" );
+      book(_nKKpi, "/TMP/nKKpi" );
     }
 
 
     /// Perform the per-event analysis
     void analyze(const Event& event) {
       const FinalState& fs = apply<FinalState>(event, "FS");
 
       map<long,int> nCount;
       int ntotal(0);
-      foreach (const Particle& p, fs.particles()) {
-	nCount[p.pdgId()] += 1;
+      for (const Particle& p : fs.particles()) {
+	nCount[p.pid()] += 1;
 	++ntotal;
       }
 
       if(ntotal==3 && nCount[310]==1 &&
 	 ((nCount[ 321]=1 &&  nCount[-211] ==1) ||
 	  (nCount[-321]=1 &&  nCount[ 211] ==1)))
-	_nKKpi->fill(event.weight());
+	_nKKpi->fill();
     }
 
 
     /// Normalise histograms etc., after the run
     void finalize() {
       double sigma = _nKKpi->val();
       double error = _nKKpi->err();
       sigma *= crossSection()/ sumOfWeights() /picobarn;
       error *= crossSection()/ sumOfWeights() /picobarn; 
       Scatter2D temphisto(refData(1, 1, 1));
-      Scatter2DPtr  mult = bookScatter2D(1, 1, 1);
+      Scatter2DPtr  mult;
+      book(mult, 1, 1, 1);
       for (size_t b = 0; b < temphisto.numPoints(); b++) {
 	const double x  = temphisto.point(b).x();
 	pair<double,double> ex = temphisto.point(b).xErrs();
 	pair<double,double> ex2 = ex;
 	if(ex2.first ==0.) ex2. first=0.0001;
 	if(ex2.second==0.) ex2.second=0.0001;
 	if (inRange(sqrtS()/GeV, x-ex2.first, x+ex2.second)) {
 	  mult->addPoint(x, sigma, ex, make_pair(error,error));
 	}
 	else {
 	  mult->addPoint(x, 0., ex, make_pair(0.,.0));
 	}
       }
     }
 
     //@}
 
 
     /// @name Histograms
     //@{
     CounterPtr _nKKpi;
     //@}
 
 
   };
 
 
   // The hook for the plugin system
   DECLARE_RIVET_PLUGIN(BESIII_2018_I1691798);
 
 
 }
diff --git a/analyses/pluginBES/BESIII_2018_I1699641.cc b/analyses/pluginBES/BESIII_2018_I1699641.cc
--- a/analyses/pluginBES/BESIII_2018_I1699641.cc
+++ b/analyses/pluginBES/BESIII_2018_I1699641.cc
@@ -1,138 +1,139 @@
 // -*- C++ -*-
 #include "Rivet/Analysis.hh"
 #include "Rivet/Projections/FinalState.hh"
 #include "Rivet/Projections/FastJets.hh"
 
 namespace Rivet {
 
 
   /// @brief Add a short analysis description here
   class BESIII_2018_I1699641 : public Analysis {
   public:
 
     /// Constructor
     DEFAULT_RIVET_ANALYSIS_CTOR(BESIII_2018_I1699641);
 
 
     /// @name Analysis methods
     //@{
 
     /// Book histograms and initialise projections before the run
     void init() {
       // Initialise and register projections
       declare(FinalState(), "FS");
       declare(UnstableParticles(), "UFS");
 
       // Book histograms
-      _cKKpipi  = bookCounter("TMP/2Kpipi" );
-      _cKKpieta = bookCounter("TMP/2Kpieta");
+      book(_cKKpipi, "TMP/2Kpipi" );
+      book(_cKKpieta, "TMP/2Kpieta");
     }
 
 
     void findChildren(const Particle & p,map<long,int> & nRes, int &ncount) {
-      foreach(const Particle &child, p.children()) {
+      for (const Particle &child : p.children()) {
 	if(child.children().empty()) {
-	  nRes[child.pdgId()]-=1;
+	  nRes[child.pid()]-=1;
 	  --ncount;
 	}
 	else
 	  findChildren(child,nRes,ncount);
       }
     }
 
     /// Perform the per-event analysis
     void analyze(const Event& event) {
       const FinalState& fs = apply<FinalState>(event, "FS");
 
       map<long,int> nCount;
       int ntotal(0);
-      foreach (const Particle& p, fs.particles()) {
-	nCount[p.pdgId()] += 1;
+      for (const Particle& p : fs.particles()) {
+	nCount[p.pid()] += 1;
 	++ntotal;
       }
       // K K pi pi
       if(ntotal==4 && nCount[310]==1 && nCount[111]==1 &&
 	 ((nCount[ 321]==1 &&nCount[-211]==1) ||
 	  (nCount[-321]==1 &&nCount[ 211]==1) ))
-	_cKKpipi->fill(event.weight());
+	_cKKpipi->fill();
       // eta resonance
       const FinalState& ufs = apply<FinalState>(event, "UFS");
-      foreach (const Particle& p, ufs.particles()) {
+      for (const Particle& p : ufs.particles()) {
 	if(p.children().empty()) continue;
-	if(p.pdgId()!=221) continue;
+	if(p.pid()!=221) continue;
 	map<long,int> nRes=nCount;
 	int ncount = ntotal;
 	findChildren(p,nRes,ncount);
 	if(ncount!=3) continue;
 	bool matched=true;
 	for(auto const & val : nRes) {
 	  if(abs(val.first)==321 || abs(val.first)==211) {
 	    continue;
 	  }
 	  else if(abs(val.first)==310) {
 	    if(val.second!=1) {
 	      matched = false;
 	      break;
 	    }
 	  }
 	  else if(val.second!=0) {
 	    matched = false;
 	    break;
 	  }
 	}
 	if(matched==false) continue;
 	if((nCount[ 321] == 1 && nCount[-211] ==1) ||
 	   (nCount[-321] == 1 && nCount[ 211] ==1))
-	  _cKKpieta->fill(event.weight());
+	  _cKKpieta->fill();
       }
     }
 
 
     /// Normalise histograms etc., after the run
     void finalize() {
       for(unsigned int ix=1;ix<3;++ix) {
 	double sigma = 0., error = 0.;
 	if(ix==1) {
 	  sigma = _cKKpipi->val();
 	  error = _cKKpipi->err();
 	}
 	else if(ix==2) {
 	  sigma = _cKKpieta->val();
 	  error = _cKKpieta->err();
 	}
     	sigma *= crossSection()/ sumOfWeights() /picobarn;
     	error *= crossSection()/ sumOfWeights() /picobarn;
 	Scatter2D temphisto(refData(ix, 1, 1));
-	Scatter2DPtr  mult = bookScatter2D(ix, 1, 1);
+	Scatter2DPtr  mult;
+        book(mult, ix, 1, 1);
 	for (size_t b = 0; b < temphisto.numPoints(); b++) {
 	  const double x  = temphisto.point(b).x();
 	  pair<double,double> ex = temphisto.point(b).xErrs();
 	  pair<double,double> ex2 = ex;
 	  if(ex2.first ==0.) ex2. first=0.0001;
 	  if(ex2.second==0.) ex2.second=0.0001;
 	  if (inRange(sqrtS()/GeV, x-ex2.first, x+ex2.second)) {
 	    mult->addPoint(x, sigma, ex, make_pair(error,error));
 	  }
 	  else {
 	    mult->addPoint(x, 0., ex, make_pair(0.,.0));
 	  }
 	}
       }
     }
 
     //@}
 
 
     /// @name Histograms
     //@{
     CounterPtr _cKKpipi,_cKKpieta;
     //@}
 
   };
 
 
   // The hook for the plugin system
   DECLARE_RIVET_PLUGIN(BESIII_2018_I1699641);
 
 
 }
diff --git a/analyses/pluginBES/BESIII_2018_I1704558.cc b/analyses/pluginBES/BESIII_2018_I1704558.cc
--- a/analyses/pluginBES/BESIII_2018_I1704558.cc
+++ b/analyses/pluginBES/BESIII_2018_I1704558.cc
@@ -1,81 +1,82 @@
 // -*- C++ -*-
 #include "Rivet/Analysis.hh"
 #include "Rivet/Projections/FinalState.hh"
 
 namespace Rivet {
 
 
   /// @brief Add a short analysis description here
   class BESIII_2018_I1704558 : public Analysis {
   public:
 
     /// Constructor
     DEFAULT_RIVET_ANALYSIS_CTOR(BESIII_2018_I1704558);
 
 
     /// @name Analysis methods
     //@{
 
     /// Book histograms and initialise projections before the run
     void init() {
 
       // Initialise and register projections
       declare(FinalState(), "FS");
 
       // Book histograms
-      _nkaon = bookCounter("TMP/kaon");
+      book(_nkaon, "TMP/kaon");
 
     }
 
 
     /// Perform the per-event analysis
     void analyze(const Event& event) {
       const FinalState& fs = apply<FinalState>(event, "FS");
       if(fs.particles().size()!=2) vetoEvent;
-      foreach (const Particle& p, fs.particles()) {
-	if(abs(p.pdgId())!=PID::KPLUS) vetoEvent;
+      for (const Particle& p : fs.particles()) {
+	if(abs(p.pid())!=PID::KPLUS) vetoEvent;
       }
-      _nkaon->fill(event.weight());
+      _nkaon->fill();
     }
 
 
     /// Normalise histograms etc., after the run
     void finalize() {
       double sigma = _nkaon->val();
       double error = _nkaon->err();
       sigma *= crossSection()/ sumOfWeights() /picobarn;
       error *= crossSection()/ sumOfWeights() /picobarn;
 	Scatter2D temphisto(refData(1, 1, 1));
-	Scatter2DPtr  mult = bookScatter2D(1, 1, 1);
+	Scatter2DPtr  mult;
+        book(mult, 1, 1, 1);
 	for (size_t b = 0; b < temphisto.numPoints(); b++) {
 	  const double x  = temphisto.point(b).x();
 	  pair<double,double> ex = temphisto.point(b).xErrs();
 	  pair<double,double> ex2 = ex;
 	  if(ex2.first ==0.) ex2. first=0.0001;
 	  if(ex2.second==0.) ex2.second=0.0001;
 	  if (inRange(sqrtS()/GeV, x-ex2.first, x+ex2.second)) {
 	    mult->addPoint(x, sigma, ex, make_pair(error,error));
 	  }
 	  else {
 	    mult->addPoint(x, 0., ex, make_pair(0.,.0));
 	  }
 	}
     }
 
     //@}
 
 
     /// @name Histograms
     //@{
     CounterPtr _nkaon;
     //@}
 
 
   };
 
 
   // The hook for the plugin system
   DECLARE_RIVET_PLUGIN(BESIII_2018_I1704558);
 
 
 }
diff --git a/analyses/pluginBES/BESIII_2019_I1718337.cc b/analyses/pluginBES/BESIII_2019_I1718337.cc
--- a/analyses/pluginBES/BESIII_2019_I1718337.cc
+++ b/analyses/pluginBES/BESIII_2019_I1718337.cc
@@ -1,80 +1,81 @@
 // -*- C++ -*-
 #include "Rivet/Analysis.hh"
 #include "Rivet/Projections/FinalState.hh"
 
 namespace Rivet {
 
 
   /// @brief Add a short analysis description here
   class BESIII_2019_I1718337 : public Analysis {
   public:
 
     /// Constructor
     DEFAULT_RIVET_ANALYSIS_CTOR(BESIII_2019_I1718337);
 
 
     /// @name Analysis methods
     //@{
 
     /// Book histograms and initialise projections before the run
     void init() {
 
       // Initialise and register projections
       declare(FinalState(), "FS");
 
       // Book histograms
-      _nproton = bookCounter("TMP/proton");
+      book(_nproton, "TMP/proton");
     }
 
 
     /// Perform the per-event analysis
     void analyze(const Event& event) {
       const FinalState& fs = apply<FinalState>(event, "FS");
       if(fs.particles().size()!=2) vetoEvent;
-      foreach (const Particle& p, fs.particles()) {
-	if(abs(p.pdgId())!=PID::PROTON) vetoEvent;
+      for (const Particle& p : fs.particles()) {
+	if(abs(p.pid())!=PID::PROTON) vetoEvent;
       }
-      _nproton->fill(event.weight());
+      _nproton->fill();
     }
 
 
     /// Normalise histograms etc., after the run
     void finalize() {
       double sigma = _nproton->val();
       double error = _nproton->err();
       sigma *= crossSection()/ sumOfWeights() /picobarn;
       error *= crossSection()/ sumOfWeights() /picobarn; 
       Scatter2D temphisto(refData(1, 1, 1));
-      Scatter2DPtr  mult = bookScatter2D(1, 1, 1);
+      Scatter2DPtr  mult;
+      book(mult, 1, 1, 1);
       for (size_t b = 0; b < temphisto.numPoints(); b++) {
 	const double x  = temphisto.point(b).x();
 	pair<double,double> ex = temphisto.point(b).xErrs();
 	pair<double,double> ex2 = ex;
 	if(ex2.first ==0.) ex2. first=0.0001;
 	if(ex2.second==0.) ex2.second=0.0001;
 	if (inRange(sqrtS()/GeV, x-ex2.first, x+ex2.second)) {
 	  mult->addPoint(x, sigma, ex, make_pair(error,error));
 	}
 	else {
 	  mult->addPoint(x, 0., ex, make_pair(0.,.0));
 	}
       }
     }
 
     //@}
 
 
     /// @name Histograms
     //@{
     CounterPtr _nproton;
     //@}
 
 
   };
 
 
   // The hook for the plugin system
   DECLARE_RIVET_PLUGIN(BESIII_2019_I1718337);
 
 
 }
diff --git a/analyses/pluginBES/BESII_2000_I505323.cc b/analyses/pluginBES/BESII_2000_I505323.cc
--- a/analyses/pluginBES/BESII_2000_I505323.cc
+++ b/analyses/pluginBES/BESII_2000_I505323.cc
@@ -1,99 +1,102 @@
 // -*- C++ -*-
 #include "Rivet/Analysis.hh"
 #include "Rivet/Projections/FinalState.hh"
 
 namespace Rivet {
 
 
   /// @brief Add a short analysis description here
   class BESII_2000_I505323 : public Analysis {
   public:
 
     /// Constructor
     DEFAULT_RIVET_ANALYSIS_CTOR(BESII_2000_I505323);
 
 
     /// @name Analysis methods
     //@{
 
     /// Book histograms and initialise projections before the run
     void init() {
       // Initialise and register projections
       declare(FinalState(), "FS");
 
       // Book histograms
-      _c_hadrons = bookCounter("/TMP/sigma_hadrons");
-      _c_muons   = bookCounter("/TMP/sigma_muons");
+      book(_c_hadrons, "/TMP/sigma_hadrons");
+      book(_c_muons,   "/TMP/sigma_muons");
     }
 
 
     /// Perform the per-event analysis
     void analyze(const Event& event) {
       const FinalState& fs = apply<FinalState>(event, "FS");
 
       map<long,int> nCount;
       int ntotal(0);
-      foreach (const Particle& p, fs.particles()) {
-	nCount[p.pdgId()] += 1;
+      for (const Particle& p : fs.particles()) {
+	nCount[p.pid()] += 1;
 	++ntotal;
       }
       // mu+mu- + photons
       if(nCount[-13]==1 and nCount[13]==1 &&
 	 ntotal==2+nCount[22])
-	_c_muons->fill(event.weight());
+	_c_muons->fill();
       // everything else
       else
-	_c_hadrons->fill(event.weight());
+	_c_hadrons->fill();
     }
 
 
     /// Normalise histograms etc., after the run
     void finalize() {
       Scatter1D R = *_c_hadrons/ *_c_muons;
       double              rval = R.point(0).x();
       pair<double,double> rerr = R.point(0).xErrs();
       double fact = crossSection()/ sumOfWeights() /nanobarn;
       double sig_h = _c_hadrons->val()*fact;
       double err_h = _c_hadrons->err()*fact;
       double sig_m = _c_muons  ->val()*fact;
       double err_m = _c_muons  ->err()*fact;
       Scatter2D temphisto(refData(1, 1, 1));
-      Scatter2DPtr hadrons  = bookScatter2D("sigma_hadrons");
-      Scatter2DPtr muons    = bookScatter2D("sigma_muons"  );
-      Scatter2DPtr     mult = bookScatter2D(1, 1, 1);
+      Scatter2DPtr hadrons;
+      book(hadrons, "sigma_hadrons");
+      Scatter2DPtr muons;
+      book(muons, "sigma_muons"  );
+      Scatter2DPtr     mult;
+      book(mult, 1, 1, 1);
       for (size_t b = 0; b < temphisto.numPoints(); b++) {
 	const double x  = temphisto.point(b).x();
 	pair<double,double> ex = temphisto.point(b).xErrs();
 	pair<double,double> ex2 = ex;
 	if(ex2.first ==0.) ex2. first=0.0001;
 	if(ex2.second==0.) ex2.second=0.0001;
 	if (inRange(sqrtS()/GeV, x-ex2.first, x+ex2.second)) {
 	  mult   ->addPoint(x, rval, ex, rerr);
 	  hadrons->addPoint(x, sig_h, ex, make_pair(err_h,err_h));
 	  muons  ->addPoint(x, sig_m, ex, make_pair(err_m,err_m));
 	}
 	else {
 	  mult   ->addPoint(x, 0., ex, make_pair(0.,.0));
 	  hadrons->addPoint(x, 0., ex, make_pair(0.,.0));
 	  muons  ->addPoint(x, 0., ex, make_pair(0.,.0));
 	}
       }
     }
 
     //@}
 
 
     /// @name Histograms
     //@{
     CounterPtr _c_hadrons, _c_muons;
     //@}
 
 
   };
 
 
   // The hook for the plugin system
   DECLARE_RIVET_PLUGIN(BESII_2000_I505323);
 
 
 }
diff --git a/analyses/pluginBES/BESII_2002_I552757.cc b/analyses/pluginBES/BESII_2002_I552757.cc
--- a/analyses/pluginBES/BESII_2002_I552757.cc
+++ b/analyses/pluginBES/BESII_2002_I552757.cc
@@ -1,99 +1,102 @@
 // -*- C++ -*-
 #include "Rivet/Analysis.hh"
 #include "Rivet/Projections/FinalState.hh"
 
 namespace Rivet {
 
 
   /// @brief Add a short analysis description here
   class BESII_2002_I552757 : public Analysis {
   public:
 
     /// Constructor
     DEFAULT_RIVET_ANALYSIS_CTOR(BESII_2002_I552757);
 
 
     /// @name Analysis methods
     //@{
 
     /// Book histograms and initialise projections before the run
     void init() {
       // Initialise and register projections
       declare(FinalState(), "FS");
 
       // Book histograms
-      _c_hadrons = bookCounter("/TMP/sigma_hadrons");
-      _c_muons   = bookCounter("/TMP/sigma_muons");
+      book(_c_hadrons, "/TMP/sigma_hadrons");
+      book(_c_muons,   "/TMP/sigma_muons");
     }
 
 
     /// Perform the per-event analysis
     void analyze(const Event& event) {
       const FinalState& fs = apply<FinalState>(event, "FS");
 
       map<long,int> nCount;
       int ntotal(0);
-      foreach (const Particle& p, fs.particles()) {
-	nCount[p.pdgId()] += 1;
+      for (const Particle& p : fs.particles()) {
+	nCount[p.pid()] += 1;
 	++ntotal;
       }
       // mu+mu- + photons
       if(nCount[-13]==1 and nCount[13]==1 &&
 	 ntotal==2+nCount[22])
-	_c_muons->fill(event.weight());
+	_c_muons->fill();
       // everything else
       else
-	_c_hadrons->fill(event.weight());
+	_c_hadrons->fill();
     }
 
 
     /// Normalise histograms etc., after the run
     void finalize() {
       Scatter1D R = *_c_hadrons/ *_c_muons;
       double              rval = R.point(0).x();
       pair<double,double> rerr = R.point(0).xErrs();
       double fact = crossSection()/ sumOfWeights() /nanobarn;
       double sig_h = _c_hadrons->val()*fact;
       double err_h = _c_hadrons->err()*fact;
       double sig_m = _c_muons  ->val()*fact;
       double err_m = _c_muons  ->err()*fact;
       Scatter2D temphisto(refData(1, 1, 1));
-      Scatter2DPtr hadrons  = bookScatter2D("sigma_hadrons");
-      Scatter2DPtr muons    = bookScatter2D("sigma_muons"  );
-      Scatter2DPtr     mult = bookScatter2D(1, 1, 1);
+      Scatter2DPtr hadrons;
+      book(hadrons, "sigma_hadrons");
+      Scatter2DPtr muons;
+      book(muons, "sigma_muons"  );
+      Scatter2DPtr     mult;
+      book(mult, 1, 1, 1);
       for (size_t b = 0; b < temphisto.numPoints(); b++) {
 	const double x  = temphisto.point(b).x();
 	pair<double,double> ex = temphisto.point(b).xErrs();
 	pair<double,double> ex2 = ex;
 	if(ex2.first ==0.) ex2. first=0.0001;
 	if(ex2.second==0.) ex2.second=0.0001;
 	if (inRange(sqrtS()/GeV, x-ex2.first, x+ex2.second)) {
 	  mult   ->addPoint(x, rval, ex, rerr);
 	  hadrons->addPoint(x, sig_h, ex, make_pair(err_h,err_h));
 	  muons  ->addPoint(x, sig_m, ex, make_pair(err_m,err_m));
 	}
 	else {
 	  mult   ->addPoint(x, 0., ex, make_pair(0.,.0));
 	  hadrons->addPoint(x, 0., ex, make_pair(0.,.0));
 	  muons  ->addPoint(x, 0., ex, make_pair(0.,.0));
 	}
       }
     }
 
     //@}
 
 
     /// @name Histograms
     //@{
     CounterPtr _c_hadrons, _c_muons;
     //@}
 
 
   };
 
 
   // The hook for the plugin system
   DECLARE_RIVET_PLUGIN(BESII_2002_I552757);
 
 
 }
diff --git a/analyses/pluginBES/BESII_2004_I622224.cc b/analyses/pluginBES/BESII_2004_I622224.cc
--- a/analyses/pluginBES/BESII_2004_I622224.cc
+++ b/analyses/pluginBES/BESII_2004_I622224.cc
@@ -1,80 +1,80 @@
 // -*- C++ -*-
 #include "Rivet/Analysis.hh"
 #include "Rivet/Projections/ChargedFinalState.hh"
 
 namespace Rivet {
 
 
   /// @brief Add a short analysis description here
   class BESII_2004_I622224 : public Analysis {
   public:
 
     /// Constructor
     DEFAULT_RIVET_ANALYSIS_CTOR(BESII_2004_I622224);
 
 
     /// @name Analysis methods
     //@{
 
     /// Book histograms and initialise projections before the run
     void init() {
       const ChargedFinalState fs;
       declare(fs, "FS");
       unsigned int iloc(0);
       if(fuzzyEquals(sqrtS()/GeV, 2.2 , 1E-3))
 	iloc = 1;
       else if(fuzzyEquals(sqrtS()/GeV, 2.6 , 1E-3))
 	iloc = 2;
       else if(fuzzyEquals(sqrtS()/GeV, 3.0 , 1E-3))
 	iloc = 3;
       else if(fuzzyEquals(sqrtS()/GeV, 3.2 , 1E-3))
 	iloc = 4;
       else if(fuzzyEquals(sqrtS()/GeV, 4.6 , 1E-3))
 	iloc = 5;
       else if(fuzzyEquals(sqrtS()/GeV, 4.8 , 1E-3))
 	iloc = 6;
       assert(iloc!=0);
-      _h_ln =  bookHisto1D( iloc   ,1,1);
-      _h_weight = 0.;
+      book(_h_ln, iloc   ,1,1);
+      book(_h_weight, "TMP/Weight");
     }
 
 
     /// Perform the per-event analysis
     void analyze(const Event& event) {
       const ChargedFinalState& fs = apply<ChargedFinalState>(event, "FS");
       if(fs.particles().size()==2 &&
-	 abs(fs.particles()[0].pdgId())==13 &&
-	 abs(fs.particles()[1].pdgId())==13) vetoEvent;
-      foreach (const Particle& p, fs.particles()) {
+	 abs(fs.particles()[0].pid())==13 &&
+	 abs(fs.particles()[1].pid())==13) vetoEvent;
+      for (const Particle& p : fs.particles()) {
 	const Vector3 mom3 = p.p3();
 	double pp = mom3.mod();
 	double xi = -log(2.*pp/sqrtS());
-	_h_ln->fill(xi,event.weight());
+	_h_ln->fill(xi);
       }
-      _h_weight+= event.weight();
+      _h_weight->fill();
     }
 
 
     /// Normalise histograms etc., after the run
     void finalize() {
-      scale(_h_ln,1./_h_weight);
+      scale(_h_ln,1./_h_weight->sumW());
     }
 
     //@}
 
 
     /// @name Histograms
     //@{
     Histo1DPtr _h_ln;
-    double _h_weight;
+    CounterPtr _h_weight;
     //@}
 
 
   };
 
 
   // The hook for the plugin system
   DECLARE_RIVET_PLUGIN(BESII_2004_I622224);
 
 
 }
diff --git a/analyses/pluginBES/BESII_2005_I685906.cc b/analyses/pluginBES/BESII_2005_I685906.cc
--- a/analyses/pluginBES/BESII_2005_I685906.cc
+++ b/analyses/pluginBES/BESII_2005_I685906.cc
@@ -1,81 +1,82 @@
 // -*- C++ -*-
 #include "Rivet/Analysis.hh"
 #include "Rivet/Projections/FinalState.hh"
 
 namespace Rivet {
 
 
   /// @brief Add a short analysis description here
   class BESII_2005_I685906 : public Analysis {
   public:
 
     /// Constructor
     DEFAULT_RIVET_ANALYSIS_CTOR(BESII_2005_I685906);
 
 
     /// @name Analysis methods
     //@{
 
     /// Book histograms and initialise projections before the run
     void init() {
 
       // Initialise and register projections
       declare(FinalState(), "FS");
 
       // Book histograms
-      _nproton = bookCounter("TMP/proton");
+      book(_nproton, "TMP/proton");
     }
 
 
     /// Perform the per-event analysis
     void analyze(const Event& event) {
       const FinalState& fs = apply<FinalState>(event, "FS");
       if(fs.particles().size()!=2) vetoEvent;
-      foreach (const Particle& p, fs.particles()) {
-	if(abs(p.pdgId())!=PID::PROTON) vetoEvent;
+      for (const Particle& p : fs.particles()) {
+	if(abs(p.pid())!=PID::PROTON) vetoEvent;
       }
-      _nproton->fill(event.weight());
+      _nproton->fill();
 
     }
 
 
     /// Normalise histograms etc., after the run
     void finalize() {
       double sigma = _nproton->val();
       double error = _nproton->err();
       sigma *= crossSection()/ sumOfWeights() /picobarn;
       error *= crossSection()/ sumOfWeights() /picobarn; 
       Scatter2D temphisto(refData(1, 1, 1));
-      Scatter2DPtr  mult = bookScatter2D(1, 1, 1);
+      Scatter2DPtr  mult;
+      book(mult, 1, 1, 1);
       for (size_t b = 0; b < temphisto.numPoints(); b++) {
 	const double x  = temphisto.point(b).x();
 	pair<double,double> ex = temphisto.point(b).xErrs();
 	pair<double,double> ex2 = ex;
 	if(ex2.first ==0.) ex2. first=0.0001;
 	if(ex2.second==0.) ex2.second=0.0001;
 	if (inRange(sqrtS()/GeV, x-ex2.first, x+ex2.second)) {
 	  mult->addPoint(x, sigma, ex, make_pair(error,error));
 	}
 	else {
 	  mult->addPoint(x, 0., ex, make_pair(0.,.0));
 	}
       }
     }
 
     //@}
 
 
     /// @name Histograms
     //@{
     CounterPtr _nproton;
     //@}
 
 
   };
 
 
   // The hook for the plugin system
   DECLARE_RIVET_PLUGIN(BESII_2005_I685906);
 
 
 }
diff --git a/analyses/pluginBES/BESII_2006_I717665.cc b/analyses/pluginBES/BESII_2006_I717665.cc
--- a/analyses/pluginBES/BESII_2006_I717665.cc
+++ b/analyses/pluginBES/BESII_2006_I717665.cc
@@ -1,99 +1,102 @@
 // -*- C++ -*-
 #include "Rivet/Analysis.hh"
 #include "Rivet/Projections/FinalState.hh"
 
 namespace Rivet {
 
 
   /// @brief Add a short analysis description here
   class BESII_2006_I717665 : public Analysis {
   public:
 
     /// Constructor
     DEFAULT_RIVET_ANALYSIS_CTOR(BESII_2006_I717665);
 
 
     /// @name Analysis methods
     //@{
 
     /// Book histograms and initialise projections before the run
     void init() {
       // Initialise and register projections
       declare(FinalState(), "FS");
 
       // Book histograms
-      _c_hadrons = bookCounter("/TMP/sigma_hadrons");
-      _c_muons   = bookCounter("/TMP/sigma_muons");
+      book(_c_hadrons, "/TMP/sigma_hadrons");
+      book(_c_muons,   "/TMP/sigma_muons");
     }
 
 
     /// Perform the per-event analysis
     void analyze(const Event& event) {
       const FinalState& fs = apply<FinalState>(event, "FS");
 
       map<long,int> nCount;
       int ntotal(0);
-      foreach (const Particle& p, fs.particles()) {
-	nCount[p.pdgId()] += 1;
+      for (const Particle& p : fs.particles()) {
+	nCount[p.pid()] += 1;
 	++ntotal;
       }
       // mu+mu- + photons
       if(nCount[-13]==1 and nCount[13]==1 &&
 	 ntotal==2+nCount[22])
-	_c_muons->fill(event.weight());
+	_c_muons->fill();
       // everything else
       else
-	_c_hadrons->fill(event.weight());
+	_c_hadrons->fill();
     }
 
 
     /// Normalise histograms etc., after the run
     void finalize() {
       Scatter1D R = *_c_hadrons/ *_c_muons;
       double              rval = R.point(0).x();
       pair<double,double> rerr = R.point(0).xErrs();
       double fact = crossSection()/ sumOfWeights() /nanobarn;
       double sig_h = _c_hadrons->val()*fact;
       double err_h = _c_hadrons->err()*fact;
       double sig_m = _c_muons  ->val()*fact;
       double err_m = _c_muons  ->err()*fact;
       Scatter2D temphisto(refData(1, 1, 1));
-      Scatter2DPtr hadrons  = bookScatter2D(2,1,1);
-      Scatter2DPtr muons    = bookScatter2D("sigma_muons"  );
-      Scatter2DPtr     mult = bookScatter2D(2, 1, 2);
+      Scatter2DPtr hadrons;
+      book(hadrons, 2,1,1);
+      Scatter2DPtr muons;
+      book(muons, "sigma_muons"  );
+      Scatter2DPtr     mult;
+      book(mult, 2, 1, 2);
       for (size_t b = 0; b < temphisto.numPoints(); b++) {
 	const double x  = temphisto.point(b).x();
 	pair<double,double> ex = temphisto.point(b).xErrs();
 	pair<double,double> ex2 = ex;
 	if(ex2.first ==0.) ex2. first=0.0001;
 	if(ex2.second==0.) ex2.second=0.0001;
 	if (inRange(sqrtS()/GeV, x-ex2.first, x+ex2.second)) {
 	  mult   ->addPoint(x, rval, ex, rerr);
 	  hadrons->addPoint(x, sig_h, ex, make_pair(err_h,err_h));
 	  muons  ->addPoint(x, sig_m, ex, make_pair(err_m,err_m));
 	}
 	else {
 	  mult   ->addPoint(x, 0., ex, make_pair(0.,.0));
 	  hadrons->addPoint(x, 0., ex, make_pair(0.,.0));
 	  muons  ->addPoint(x, 0., ex, make_pair(0.,.0));
 	}
       }
     }
 
     //@}
 
 
     /// @name Histograms
     //@{
     CounterPtr _c_hadrons, _c_muons;
     //@}
 
 
   };
 
 
   // The hook for the plugin system
   DECLARE_RIVET_PLUGIN(BESII_2006_I717665);
 
 
 }
diff --git a/analyses/pluginBES/BESII_2007_I750713.cc b/analyses/pluginBES/BESII_2007_I750713.cc
--- a/analyses/pluginBES/BESII_2007_I750713.cc
+++ b/analyses/pluginBES/BESII_2007_I750713.cc
@@ -1,180 +1,181 @@
 // -*- C++ -*-
 #include "Rivet/Analysis.hh"
 #include "Rivet/Projections/FinalState.hh"
 #include "Rivet/Projections/UnstableParticles.hh"
 
 namespace Rivet {
 
 
   /// @brief Add a short analysis description here
   class BESII_2007_I750713 : public Analysis {
   public:
 
     /// Constructor
     DEFAULT_RIVET_ANALYSIS_CTOR(BESII_2007_I750713);
 
 
     /// @name Analysis methods
     //@{
 
     /// Book histograms and initialise projections before the run
     void init() {
 
       // Initialise and register projections
       declare(FinalState(), "FS");
       declare(UnstableParticles(), "UFS");
 
       // Book histograms
       for(unsigned int ix=1;ix<19;++ix) {
 	stringstream ss;
 	ss << "TMP/n" << ix;
-	_nMeson[ix]= bookCounter(ss.str());
+	book(_nMeson[ix], ss.str());
       }
 
     }
 
     void findChildren(const Particle & p,map<long,int> & nRes, int &ncount) {
-      foreach(const Particle &child, p.children()) {
+      for (const Particle &child : p.children()) {
 	if(child.children().empty()) {
-	  nRes[child.pdgId()]-=1;
+	  nRes[child.pid()]-=1;
 	  --ncount;
 	}
 	else
 	  findChildren(child,nRes,ncount);
       }
     }
 
     /// Perform the per-event analysis
     void analyze(const Event& event) {
       const FinalState& fs = apply<FinalState>(event, "FS");
 
       map<long,int> nCount;
       int ntotal(0);
-      foreach (const Particle& p, fs.particles()) {
-	nCount[p.pdgId()] += 1;
+      for (const Particle& p : fs.particles()) {
+	nCount[p.pid()] += 1;
 	++ntotal;
       }
       const FinalState& ufs = apply<FinalState>(event, "UFS");
       
-      foreach (const Particle& p, ufs.particles()) {
+      for (const Particle& p : ufs.particles()) {
       	if(p.children().empty()) continue;
-      	if(p.pdgId()!=221 && p.pdgId()!=333) continue;
+      	if(p.pid()!=221 && p.pid()!=333) continue;
       	map<long,int> nRes = nCount;
       	int ncount = ntotal;
       	findChildren(p,nRes,ncount);
 	// eta
-      	if(p.pdgId()==221) {
+      	if(p.pid()==221) {
        	  if(ncount==4) {
       	    bool matched = true;
       	    for(auto const & val : nRes) {
       	      if(abs(val.first)==211) {
       		if(val.second!=2) {
       		  matched = false;
       		  break;
       		}
       	      }
       	      else if(val.second!=0) {
       		matched = false;
       		break;
       	      }
       	    }
-      	    if(matched) _nMeson[12]->fill(event.weight());
+      	    if(matched) _nMeson[12]->fill();
       	  }
 	}
-       	else if(p.pdgId()==333) {
+       	else if(p.pid()==333) {
        	  if(ncount!=1) continue;
        	  bool matched = true;
        	  for(auto const & val : nRes) {
        	    if(abs(val.first)==321) {
        	      if(val.second!=1) {
        		matched = false;
        		break;
        	      }
        	    }
        	    else if(val.second!=0) {
        	      matched = false;
        	      break;
        	    }
        	  }
        	  if(matched)
-       	    _nMeson[7]->fill(event.weight());
+       	    _nMeson[7]->fill();
       	}
       }
       if(ntotal==3 &&  nCount[111]==1 &&
 	 nCount[-2212] == 1 && nCount[ 2212]==1)
-	_nMeson[16]->fill(event.weight());
+	_nMeson[16]->fill();
       else if(ntotal==4) {
 	if(nCount[-211] == 2 && nCount[ 211]==2)
-	  _nMeson[3]->fill(event.weight());
+	  _nMeson[3]->fill();
 	else if(nCount[-211] == 1 && nCount[ 211]==1 &&
 		nCount[-321] == 1 && nCount[ 321]==1)
-	  _nMeson[4]->fill(event.weight());
+	  _nMeson[4]->fill();
 	else if(nCount[-321] == 2 && nCount[ 321]==2)
-	  _nMeson[6]->fill(event.weight());
+	  _nMeson[6]->fill();
 	else if(nCount[-211 ] == 1 && nCount[ 211 ]==1 &&
 		nCount[-2212] == 1 && nCount[ 2212]==1)
-	  _nMeson[8]->fill(event.weight());
+	  _nMeson[8]->fill();
 	else if(nCount[-321 ] == 1 && nCount[ 321 ]==1 &&
 		nCount[-2212] == 1 && nCount[ 2212]==1)
-	  _nMeson[9]->fill(event.weight());
+	  _nMeson[9]->fill();
       }
       else if(ntotal==5 && nCount[111]==1) {
 	if(nCount[-211] == 2 && nCount[ 211]==2)
-	  _nMeson[13]->fill(event.weight());
+	  _nMeson[13]->fill();
 	else if(nCount[-211] == 1 && nCount[ 211]==1 &&
 		nCount[-321] == 1 && nCount[ 321]==1)
-	  _nMeson[14]->fill(event.weight());
+	  _nMeson[14]->fill();
 	else if(nCount[-321] == 2 && nCount[ 321]==2)
-	  _nMeson[15]->fill(event.weight());
+	  _nMeson[15]->fill();
 	else if(nCount[-211 ] == 1 && nCount[ 211 ]==1 &&
 		nCount[-2212] == 1 && nCount[ 2212]==1)
-	  _nMeson[17]->fill(event.weight());
+	  _nMeson[17]->fill();
       }
       else if(ntotal==6 && nCount[211]==3 && nCount[-211]==3)
-	_nMeson[11]->fill(event.weight());
+	_nMeson[11]->fill();
       else if(ntotal==7 && nCount[111]==1 &&
 	      nCount[211]==3 && nCount[-211]==3)
-	_nMeson[18]->fill(event.weight());
+	_nMeson[18]->fill();
     }
 
 
     /// Normalise histograms etc., after the run
     void finalize() {
       for(unsigned int ix=3;ix<19;++ix) {
         if(ix==5 || ix==10) continue;
 	double sigma = _nMeson[ix]->val();
 	double error = _nMeson[ix]->err();
     	sigma *= crossSection()/ sumOfWeights() /picobarn;
     	error *= crossSection()/ sumOfWeights() /picobarn; 
 	Scatter2D temphisto(refData(1, 1, ix));
-    	Scatter2DPtr  mult = bookScatter2D(1, 1, ix);
+    	Scatter2DPtr  mult;
+        book(mult, 1, 1, ix);
 	for (size_t b = 0; b < temphisto.numPoints(); b++) {
 	  const double x  = temphisto.point(b).x();
 	  pair<double,double> ex = temphisto.point(b).xErrs();
 	  pair<double,double> ex2 = ex;
 	  if(ex2.first ==0.) ex2. first=0.0001;
 	  if(ex2.second==0.) ex2.second=0.0001;
 	  if (inRange(sqrtS()/GeV, x-ex2.first, x+ex2.second)) {
 	    mult->addPoint(x, sigma, ex, make_pair(error,error));
 	  }
 	  else {
 	    mult->addPoint(x, 0., ex, make_pair(0.,.0));
 	  }
 	}
       }
     }
     //@}
 
     /// @name Histograms
     //@{
     CounterPtr _nMeson[19];
     //@}
 
   };
 
 
   // The hook for the plugin system
   DECLARE_RIVET_PLUGIN(BESII_2007_I750713);
 
 
 }
diff --git a/analyses/pluginBES/BESII_2007_I762901.cc b/analyses/pluginBES/BESII_2007_I762901.cc
--- a/analyses/pluginBES/BESII_2007_I762901.cc
+++ b/analyses/pluginBES/BESII_2007_I762901.cc
@@ -1,175 +1,176 @@
 // -*- C++ -*-
 #include "Rivet/Analysis.hh"
 #include "Rivet/Projections/FinalState.hh"
 #include "Rivet/Projections/UnstableParticles.hh"
 
 namespace Rivet {
 
 
   /// @brief Add a short analysis description here
   class BESII_2007_I762901 : public Analysis {
   public:
 
     /// Constructor
     DEFAULT_RIVET_ANALYSIS_CTOR(BESII_2007_I762901);
 
 
     /// @name Analysis methods
     //@{
 
     /// Book histograms and initialise projections before the run
     void init() {
 
       // Initialise and register projections
       declare(FinalState(), "FS");
       declare(UnstableParticles(), "UFS");
 
       // Book histograms
       for(unsigned int ix=1;ix<11;++ix) {
 	stringstream ss;
 	ss << "TMP/n" << ix;
-	_nMeson[ix]= bookCounter(ss.str());
+	book(_nMeson[ix], ss.str());
       }
 
     }
 
     void findChildren(const Particle & p,map<long,int> & nRes, int &ncount) {
-      foreach(const Particle &child, p.children()) {
+      for(const Particle &child : p.children()) {
 	if(child.children().empty()) {
-	  nRes[child.pdgId()]-=1;
+	  nRes[child.pid()]-=1;
 	  --ncount;
 	}
 	else
 	  findChildren(child,nRes,ncount);
       }
     }
 
     /// Perform the per-event analysis
     void analyze(const Event& event) {
       const FinalState& fs = apply<FinalState>(event, "FS");
 
       map<long,int> nCount;
       int ntotal(0);
-      foreach (const Particle& p, fs.particles()) {
-	nCount[p.pdgId()] += 1;
+      for (const Particle& p : fs.particles()) {
+	nCount[p.pid()] += 1;
 	++ntotal;
       }
       if(ntotal==6) {
 	if(nCount[211]==2 && nCount[-211]==2 && nCount[321]==1 && nCount[-321]==1)
-	  _nMeson[1]->fill(event.weight());
+	  _nMeson[1]->fill();
 	else if(nCount[211]==1 && nCount[-211]==1 && nCount[321]==2 && nCount[-321]==2)
-	  _nMeson[2]->fill(event.weight());
+	  _nMeson[2]->fill();
 	else if(nCount[211]==2 && nCount[-211]==2 && nCount[2212]==1 && nCount[-2212]==1)
-	  _nMeson[3]->fill(event.weight());
+	  _nMeson[3]->fill();
 	else if(nCount[211]==3 && nCount[-211]==3)
-	  _nMeson[4]->fill(event.weight());
+	  _nMeson[4]->fill();
       }
       else if(ntotal==7) {
 	if(nCount[211]==2 && nCount[-211]==2 && nCount[321]==1 && nCount[-321]==1 && nCount[111]==1)
-	  _nMeson[5]->fill(event.weight());
+	  _nMeson[5]->fill();
       }
       const FinalState& ufs = apply<FinalState>(event, "UFS");
-      foreach (const Particle& p, ufs.particles()) {
+      for (const Particle& p : ufs.particles()) {
        	if(p.children().empty()) continue;
-       	if(p.pdgId()!=113 && abs(p.pdgId())!=313) continue;
+       	if(p.pid()!=113 && abs(p.pid())!=313) continue;
      	map<long,int> nRes = nCount;
      	int ncount = ntotal;
      	findChildren(p,nRes,ncount);
-      	if(p.pdgId()==113) {
+      	if(p.pid()==113) {
        	  if(ncount!=2) continue;
       	  unsigned int nPi(0),nK(0),nProt(0);
        	  bool matched = true;
        	  for(auto const & val : nRes) {
        	    if(abs(val.first)==211 && val.second==1) {
        	      nPi+=1;
        	    }
        	    else if(abs(val.first)==321 && val.second==1) {
        	      nK+=1;
        	    }
        	    else if(abs(val.first)==2212 && val.second==1) {
        	      nProt+=1;
        	    }
        	    else if(val.second!=0) {
        	      matched = false;
        	      break;
        	    }
        	  }
        	  if(matched) {
        	    if(nProt==2 && nPi==0 && nK==0)
-       	      _nMeson[9]->fill(event.weight());
+       	      _nMeson[9]->fill();
        	    else if(nProt==0 && nPi==2 && nK==0)
-       	      _nMeson[7]->fill(event.weight());
+       	      _nMeson[7]->fill();
        	    else if(nProt==0 && nPi==0 && nK==2)
-       	      _nMeson[8]->fill(event.weight());
+       	      _nMeson[8]->fill();
        	  }
        	}
-     	else if(abs(p.pdgId())==313) {
+     	else if(abs(p.pid())==313) {
        	  if(ncount!=2) continue;
       	  unsigned int npi(0),nK(0);
       	  bool matched = true;
-      	  int ipi = p.pdgId()==313 ?  211 : -211;
-       	  int iK  = p.pdgId()==313 ? -321 :  321;
+      	  int ipi = p.pid()==313 ?  211 : -211;
+       	  int iK  = p.pid()==313 ? -321 :  321;
       	  for(auto const & val : nRes) {
       	    if(abs(val.first)== ipi && val.second==1) {
       	      npi+=1;
       	    }
       	    else if(abs(val.first)==iK && val.second==1) {
       	      nK+=1;
       	    }
        	    else if(val.second!=0) {
        	      matched = false;
        	      break;
        	    }
        	  }
        	  if(matched) {
        	    if(npi==1&&nK==1)
-       	      _nMeson[10]->fill(event.weight());
+       	      _nMeson[10]->fill();
        	  }
        	}
       }
     }
 
 
     /// Normalise histograms etc., after the run
     void finalize() {
       for(unsigned int ix=1;ix<11;++ix) {
 	if(ix==6) continue;
 	double sigma = _nMeson[ix]->val();
 	double error = _nMeson[ix]->err();
     	sigma *= crossSection()/ sumOfWeights() /picobarn;
     	error *= crossSection()/ sumOfWeights() /picobarn;
 	Scatter2D temphisto(refData(1, 1, ix));
-	Scatter2DPtr  mult = bookScatter2D(1, 1, ix);
+	Scatter2DPtr  mult;
+        book(mult, 1, 1, ix);
 	for (size_t b = 0; b < temphisto.numPoints(); b++) {
 	  const double x  = temphisto.point(b).x();
 	  pair<double,double> ex = temphisto.point(b).xErrs();
 	  pair<double,double> ex2 = ex;
 	  if(ex2.first ==0.) ex2. first=0.0001;
 	  if(ex2.second==0.) ex2.second=0.0001;
 	  if (inRange(sqrtS()/GeV, x-ex2.first, x+ex2.second)) {
 	    mult->addPoint(x, sigma, ex, make_pair(error,error));
 	  }
 	  else {
 	    mult->addPoint(x, 0., ex, make_pair(0.,.0));
 	  }
 	}
       }
     }
 
     //@}
 
 
     /// @name Histograms
     //@{
     CounterPtr _nMeson[11];
     //@}
 
 
   };
 
 
   // The hook for the plugin system
   DECLARE_RIVET_PLUGIN(BESII_2007_I762901);
 
 
 }
diff --git a/analyses/pluginBES/BESII_2007_I763880.cc b/analyses/pluginBES/BESII_2007_I763880.cc
--- a/analyses/pluginBES/BESII_2007_I763880.cc
+++ b/analyses/pluginBES/BESII_2007_I763880.cc
@@ -1,204 +1,205 @@
 // -*- C++ -*-
 #include "Rivet/Analysis.hh"
 #include "Rivet/Projections/FinalState.hh"
 #include "Rivet/Projections/UnstableParticles.hh"
 
 namespace Rivet {
 
 
   /// @brief Add a short analysis description here
   class BESII_2007_I763880 : public Analysis {
   public:
 
     /// Constructor
     DEFAULT_RIVET_ANALYSIS_CTOR(BESII_2007_I763880);
 
 
     /// @name Analysis methods
     //@{
 
     /// Book histograms and initialise projections before the run
     void init() {
 
       // Initialise and register projections
       declare(FinalState(), "FS");
       declare(UnstableParticles(), "UFS");
 
       // Book histograms
       for(unsigned int ix=1;ix<8;++ix) {
 	stringstream ss;
 	ss << "TMP/n" << ix;
-	_nMeson[ix]= bookCounter(ss.str());
+	book(_nMeson[ix], ss.str());
       }
     }
 
     void findChildren(const Particle & p,map<long,int> & nRes, int &ncount) {
-      foreach(const Particle &child, p.children()) {
+      for (const Particle &child : p.children()) {
 	if(child.children().empty()) {
-	  nRes[child.pdgId()]-=1;
+	  nRes[child.pid()]-=1;
 	  --ncount;
 	}
 	else
 	  findChildren(child,nRes,ncount);
       }
     }
 
     /// Perform the per-event analysis
     void analyze(const Event& event) {
       const FinalState& fs = apply<FinalState>(event, "FS");
 
       map<long,int> nCount;
       int ntotal(0);
-      foreach (const Particle& p, fs.particles()) {
-	nCount[p.pdgId()] += 1;
+      for (const Particle& p : fs.particles()) {
+	nCount[p.pid()] += 1;
 	++ntotal;
       }
       const FinalState& ufs = apply<FinalState>(event, "UFS");
-      foreach (const Particle& p, ufs.particles()) {
+      for (const Particle& p : ufs.particles()) {
 	if(p.children().empty()) continue;
-	if(p.pdgId()!=223 && p.pdgId()!=113&&abs(p.pdgId())!=313&& abs(p.pdgId())!=323)
+	if(p.pid()!=223 && p.pid()!=113&&abs(p.pid())!=313&& abs(p.pid())!=323)
 	  continue;
 	map<long,int> nRes = nCount;
 	int ncount = ntotal;
 	findChildren(p,nRes,ncount);
-	if(p.pdgId()==113) {
+	if(p.pid()==113) {
 	  if(ncount!=3) continue;
 	  unsigned int npi(0),nK(0);
 	  bool matched = true;
 	  for(auto const & val : nRes) {
 	    if(abs(val.first)==111 && val.second==1) {
 	      npi+=1;
 	    }
 	    else if(abs(val.first)==321 && val.second==1) {
 	      nK+=1;
 	    }
 	    else if(val.second!=0) {
 	      matched = false;
 	      break;
 	    }
 	  }
 	  if(matched) {
 	    if(npi==1&&nK==2)
-	      _nMeson[4]->fill(event.weight());
+	      _nMeson[4]->fill();
 	  }
 	}
-	else if(abs(p.pdgId())==213) {
+	else if(abs(p.pid())==213) {
 	  if(ncount!=3) continue;
 	  unsigned int npi(0),nK(0);
 	  bool matched = true;
-	  int ipi = p.pdgId()==213 ? -211 : 211;
+	  int ipi = p.pid()==213 ? -211 : 211;
 	  for(auto const & val : nRes) {
 	    if(abs(val.first)== ipi && val.second==1) {
 	      npi+=1;
 	    }
 	    else if(abs(val.first)==321 && val.second==1) {
 	      nK+=1;
 	    }
 	    else if(val.second!=0) {
 	      matched = false;
 	      break;
 	    }
 	  }
 	  if(matched) {
 	    if(npi==1&&nK==2)
-	      _nMeson[5]->fill(event.weight());
+	      _nMeson[5]->fill();
 	  }
 	}
-	else if(abs(p.pdgId())==313) {
+	else if(abs(p.pid())==313) {
 	  if(ncount!=3) continue;
 	  unsigned int npi(0),nK(0),npi0(0);
 	  bool matched = true;
-	  int ipi = p.pdgId()==313 ?  211 : -211;
-	  int iK  = p.pdgId()==313 ? -321 :  321;
+	  int ipi = p.pid()==313 ?  211 : -211;
+	  int iK  = p.pid()==313 ? -321 :  321;
 	  for(auto const & val : nRes) {
 	    if(abs(val.first)== ipi && val.second==1) {
 	      npi+=1;
 	    }
 	    else if(abs(val.first)==iK && val.second==1) {
 	      nK+=1;
 	    }
 	    if(abs(val.first)== 111 && val.second==1) {
 	      npi0+=1;
 	    }
 	    else if(val.second!=0) {
 	      matched = false;
 	      break;
 	    }
 	  }
 	  if(matched) {
 	    if(npi==1&&nK==1&&npi0==1)
-	      _nMeson[6]->fill(event.weight());
+	      _nMeson[6]->fill();
 	  }
 	}
-	else if(abs(p.pdgId())==323) {
+	else if(abs(p.pid())==323) {
 	  if(ncount!=3) continue;
 	  unsigned int npi(0),nK(0),npi0(0);
 	  bool matched = true;
-	  int ipi = p.pdgId()==323 ?  211 : -211;
-	  int iK  = p.pdgId()==323 ? -321 :  321;
+	  int ipi = p.pid()==323 ?  211 : -211;
+	  int iK  = p.pid()==323 ? -321 :  321;
 	  for(auto const & val : nRes) {
 	    if(abs(val.first)== ipi && val.second==1) {
 	      npi+=1;
 	    }
 	    else if(abs(val.first)==iK && val.second==1) {
 	      nK+=1;
 	    }
 	    if(abs(val.first)== 111 && val.second==1) {
 	      npi0+=1;
 	    }
 	    else if(val.second!=0) {
 	      matched = false;
 	      break;
 	    }
 	  }
 	  if(matched) {
 	    if(npi==1&&nK==1&&npi0==1)
-	      _nMeson[7]->fill(event.weight());
+	      _nMeson[7]->fill();
 	  }
 	}
       }
     }
 
 
     /// Normalise histograms etc., after the run
     void finalize() {
       for(unsigned int ix=4;ix<8;++ix) {
 	double sigma = _nMeson[ix]->val();
 	double error = _nMeson[ix]->err();
     	sigma *= crossSection()/ sumOfWeights() /nanobarn;
     	error *= crossSection()/ sumOfWeights() /nanobarn;
 	Scatter2D temphisto(refData(1, 1, ix));
-	Scatter2DPtr  mult = bookScatter2D(1, 1, ix);
+	Scatter2DPtr  mult;
+        book(mult, 1, 1, ix);
 	for (size_t b = 0; b < temphisto.numPoints(); b++) {
 	  const double x  = temphisto.point(b).x();
 	  pair<double,double> ex = temphisto.point(b).xErrs();
 	  pair<double,double> ex2 = ex;
 	  if(ex2.first ==0.) ex2. first=0.0001;
 	  if(ex2.second==0.) ex2.second=0.0001;
 	  if (inRange(sqrtS()/GeV, x-ex2.first, x+ex2.second)) {
 	    mult->addPoint(x, sigma, ex, make_pair(error,error));
 	  }
 	  else {
 	    mult->addPoint(x, 0., ex, make_pair(0.,.0));
 	  }
 	}
       }
     }
 
     //@}
 
 
     /// @name Histograms
     //@{
     CounterPtr _nMeson[8];
     //@}
 
 
   };
 
 
   // The hook for the plugin system
   DECLARE_RIVET_PLUGIN(BESII_2007_I763880);
 
 
 }
diff --git a/analyses/pluginBES/BESII_2008_I801208.cc b/analyses/pluginBES/BESII_2008_I801208.cc
--- a/analyses/pluginBES/BESII_2008_I801208.cc
+++ b/analyses/pluginBES/BESII_2008_I801208.cc
@@ -1,117 +1,118 @@
 // -*- C++ -*-
 #include "Rivet/Analysis.hh"
 #include "Rivet/Projections/FinalState.hh"
 
 namespace Rivet {
 
 
   /// @brief Add a short analysis description here
   class BESII_2008_I801208 : public Analysis {
   public:
 
     /// Constructor
     DEFAULT_RIVET_ANALYSIS_CTOR(BESII_2008_I801208);
 
 
     /// @name Analysis methods
     //@{
 
     /// Book histograms and initialise projections before the run
     void init() {
 
       // Initialise and register projections
       declare(FinalState(), "FS");
 
       // Book histograms
       for(unsigned int ix=1;ix<7;++ix) {
 	stringstream ss;
 	ss << "TMP/n" << ix;
-	_nMeson[ix]= bookCounter(ss.str());
+	book(_nMeson[ix], ss.str());
       }
     }
 
 
     /// Perform the per-event analysis
     void analyze(const Event& event) {
       const FinalState& fs = apply<FinalState>(event, "FS");
 
       map<long,int> nCount;
       int ntotal(0);
-      foreach (const Particle& p, fs.particles()) {
-	nCount[p.pdgId()] += 1;
+      for (const Particle& p : fs.particles()) {
+	nCount[p.pid()] += 1;
 	++ntotal;
       }
       if(nCount[310]!=1) vetoEvent;
 
       if(ntotal==3) {
 	if((nCount[ 211]==1 && nCount[-321]==1) ||
 	   (nCount[-211]==1 && nCount[ 321]==1) )
-	  _nMeson[1]->fill(event.weight());
+	  _nMeson[1]->fill();
       }
       else if(ntotal==4&&nCount[111]==1) {
 	if((nCount[ 211]==1 && nCount[-321]==1) ||
 	   (nCount[-211]==1 && nCount[ 321]==1) )
-	  _nMeson[2]->fill(event.weight());
+	  _nMeson[2]->fill();
       }
       else if(ntotal==5) {
 	if((nCount[ 211]==2 && nCount[-211]==1 && nCount[-321]==1) ||
 	   (nCount[-211]==2 && nCount[ 211]==1 && nCount[ 321]==1) )
-	  _nMeson[3]->fill(event.weight());
+	  _nMeson[3]->fill();
 	if(((nCount[ 211]==1 &&  nCount[-321]==1) ||
 	    (nCount[-211]==1 &&  nCount[ 321]==1) ) && nCount[111]==2)
-	  _nMeson[6]->fill(event.weight());
+	  _nMeson[6]->fill();
       }
       else if(ntotal==6&&nCount[111]==1) {
 	if((nCount[ 211]==2 && nCount[-211]==1 && nCount[-321]==1) ||
 	   (nCount[-211]==2 && nCount[ 211]==1 && nCount[ 321]==1) )
-	  _nMeson[4]->fill(event.weight());
+	  _nMeson[4]->fill();
       }
       else if(ntotal==7) {
 	if((nCount[ 211]==3 && nCount[-211]==2 && nCount[-321]==1) ||
 	   (nCount[-211]==3 && nCount[ 211]==2 && nCount[ 321]==1) )
-	  _nMeson[5]->fill(event.weight());
+	  _nMeson[5]->fill();
       }
     }
 
     /// Normalise histograms etc., after the run
     void finalize() {
       for(unsigned int ix=1;ix<7;++ix) {
 	double sigma = _nMeson[ix]->val();
 	double error = _nMeson[ix]->err();
     	sigma *= crossSection()/ sumOfWeights() /picobarn;
     	error *= crossSection()/ sumOfWeights() /picobarn; 
 	Scatter2D temphisto(refData(1, 1, ix));
-    	Scatter2DPtr  mult = bookScatter2D(1, 1, ix);
+    	Scatter2DPtr  mult;
+        book(mult, 1, 1, ix);
 	for (size_t b = 0; b < temphisto.numPoints(); b++) {
 	  const double x  = temphisto.point(b).x();
 	  pair<double,double> ex = temphisto.point(b).xErrs();
 	  pair<double,double> ex2 = ex;
 	  if(ex2.first ==0.) ex2. first=0.0001;
 	  if(ex2.second==0.) ex2.second=0.0001;
 	  if (inRange(sqrtS()/GeV, x-ex2.first, x+ex2.second)) {
 	    mult->addPoint(x, sigma, ex, make_pair(error,error));
 	  }
 	  else {
 	    mult->addPoint(x, 0., ex, make_pair(0.,.0));
 	  }
 	}
       }
     }
 
     //@}
 
 
     /// @name Histograms
     //@{
     CounterPtr _nMeson[7];
     //@}
 
 
   };
 
 
   // The hook for the plugin system
   DECLARE_RIVET_PLUGIN(BESII_2008_I801208);
 
 
 }
diff --git a/analyses/pluginBES/BESII_2008_I801210.cc b/analyses/pluginBES/BESII_2008_I801210.cc
--- a/analyses/pluginBES/BESII_2008_I801210.cc
+++ b/analyses/pluginBES/BESII_2008_I801210.cc
@@ -1,108 +1,109 @@
 // -*- C++ -*-
 #include "Rivet/Analysis.hh"
 #include "Rivet/Projections/FinalState.hh"
 
 namespace Rivet {
 
 
   /// @brief Add a short analysis description here
   class BESII_2008_I801210 : public Analysis {
   public:
 
     /// Constructor
     DEFAULT_RIVET_ANALYSIS_CTOR(BESII_2008_I801210);
 
 
     /// @name Analysis methods
     //@{
 
     /// Book histograms and initialise projections before the run
     void init() {
 
       // Initialise and register projections
       declare(FinalState(), "FS");
 
       // Book histograms
       for(unsigned int ix=1;ix<6;++ix) {
 	stringstream ss;
 	ss << "TMP/n" << ix;
-	_nMeson[ix]= bookCounter(ss.str());
+	book(_nMeson[ix], ss.str());
       }
     }
 
 
     /// Perform the per-event analysis
     void analyze(const Event& event) {
       const FinalState& fs = apply<FinalState>(event, "FS");
 
       map<long,int> nCount;
       int ntotal(0);
-      foreach (const Particle& p, fs.particles()) {
-	nCount[p.pdgId()] += 1;
+      for (const Particle& p : fs.particles()) {
+	nCount[p.pid()] += 1;
 	++ntotal;
       }
       if(nCount[111]!=2) vetoEvent;
 
       if(ntotal==4) {
 	if(nCount[211]==1 && nCount[-211]==1)
-	  _nMeson[1]->fill(event.weight());
+	  _nMeson[1]->fill();
 	else if(nCount[321]==1 && nCount[-321]==1)
-	  _nMeson[2]->fill(event.weight());
+	  _nMeson[2]->fill();
       }
       else if(ntotal==6) {
 	if(nCount[211]==2 && nCount[-211]==2)
-	  _nMeson[3]->fill(event.weight());
+	  _nMeson[3]->fill();
 	else if(nCount[321]==1 && nCount[-321]==1 &&
 		nCount[211]==1 && nCount[-211]==1)
-	  _nMeson[4]->fill(event.weight());
+	  _nMeson[4]->fill();
       }
       else if(ntotal==8) {
 	if(nCount[211]==3 && nCount[-211]==3)
-	  _nMeson[5]->fill(event.weight());
+	  _nMeson[5]->fill();
       }
       
     }
 
 
     /// Normalise histograms etc., after the run
     void finalize() {
       for(unsigned int ix=1;ix<6;++ix) {
 	double sigma = _nMeson[ix]->val();
 	double error = _nMeson[ix]->err();
     	sigma *= crossSection()/ sumOfWeights() /picobarn;
     	error *= crossSection()/ sumOfWeights() /picobarn; 
 	Scatter2D temphisto(refData(1, 1, ix));
-    	Scatter2DPtr  mult = bookScatter2D(1, 1, ix);
+    	Scatter2DPtr  mult;
+        book(mult, 1, 1, ix);
 	for (size_t b = 0; b < temphisto.numPoints(); b++) {
 	  const double x  = temphisto.point(b).x();
 	  pair<double,double> ex = temphisto.point(b).xErrs();
 	  pair<double,double> ex2 = ex;
 	  if(ex2.first ==0.) ex2. first=0.0001;
 	  if(ex2.second==0.) ex2.second=0.0001;
 	  if (inRange(sqrtS()/GeV, x-ex2.first, x+ex2.second)) {
 	    mult->addPoint(x, sigma, ex, make_pair(error,error));
 	  }
 	  else {
 	    mult->addPoint(x, 0., ex, make_pair(0.,.0));
 	  }
 	}
       }
     }
 
     //@}
 
 
     /// @name Histograms
     //@{
     CounterPtr _nMeson[6];
     //@}
 
 
   };
 
 
   // The hook for the plugin system
   DECLARE_RIVET_PLUGIN(BESII_2008_I801210);
 
 
 }
diff --git a/analyses/pluginBES/BESII_2009_I814778.cc b/analyses/pluginBES/BESII_2009_I814778.cc
--- a/analyses/pluginBES/BESII_2009_I814778.cc
+++ b/analyses/pluginBES/BESII_2009_I814778.cc
@@ -1,98 +1,101 @@
 // -*- C++ -*-
 #include "Rivet/Analysis.hh"
 #include "Rivet/Projections/FinalState.hh"
 
 namespace Rivet {
 
 
   /// @brief Add a short analysis description here
   class BESII_2009_I814778 : public Analysis {
   public:
 
     /// Constructor
     DEFAULT_RIVET_ANALYSIS_CTOR(BESII_2009_I814778);
 
 
     /// @name Analysis methods
     //@{
 
     /// Book histograms and initialise projections before the run
     void init() {
       // Initialise and register projections
       declare(FinalState(), "FS");
       // Book histograms
-      _c_hadrons = bookCounter("/TMP/sigma_hadrons");
-      _c_muons   = bookCounter("/TMP/sigma_muons");
+      book(_c_hadrons, "/TMP/sigma_hadrons");
+      book(_c_muons, "/TMP/sigma_muons");
     }
 
 
     /// Perform the per-event analysis
     void analyze(const Event& event) {
       const FinalState& fs = apply<FinalState>(event, "FS");
 
       map<long,int> nCount;
       int ntotal(0);
-      foreach (const Particle& p, fs.particles()) {
-	nCount[p.pdgId()] += 1;
+      for (const Particle& p : fs.particles()) {
+	nCount[p.pid()] += 1;
 	++ntotal;
       }
       // mu+mu- + photons
       if(nCount[-13]==1 and nCount[13]==1 &&
 	 ntotal==2+nCount[22])
-	_c_muons->fill(event.weight());
+	_c_muons->fill();
       // everything else
       else
-	_c_hadrons->fill(event.weight());
+	_c_hadrons->fill();
     }
 
 
     /// Normalise histograms etc., after the run
     void finalize() {
       Scatter1D R = *_c_hadrons/ *_c_muons;
       double              rval = R.point(0).x();
       pair<double,double> rerr = R.point(0).xErrs();
       double fact = crossSection()/ sumOfWeights() /nanobarn;
       double sig_h = _c_hadrons->val()*fact;
       double err_h = _c_hadrons->err()*fact;
       double sig_m = _c_muons  ->val()*fact;
       double err_m = _c_muons  ->err()*fact;
       Scatter2D temphisto(refData(1, 1, 1));
-      Scatter2DPtr hadrons  = bookScatter2D("sigma_hadrons");
-      Scatter2DPtr muons    = bookScatter2D("sigma_muons"  );
-      Scatter2DPtr     mult = bookScatter2D(1, 1, 1);
+      Scatter2DPtr hadrons;
+      book(hadrons, "sigma_hadrons");
+      Scatter2DPtr muons;
+      book(muons, "sigma_muons"  );
+      Scatter2DPtr     mult;
+      book(mult, 1, 1, 1);
       for (size_t b = 0; b < temphisto.numPoints(); b++) {
 	const double x  = temphisto.point(b).x();
 	pair<double,double> ex = temphisto.point(b).xErrs();
 	pair<double,double> ex2 = ex;
 	if(ex2.first ==0.) ex2. first=0.0001;
 	if(ex2.second==0.) ex2.second=0.0001;
 	if (inRange(sqrtS()/GeV, x-ex2.first, x+ex2.second)) {
 	  mult   ->addPoint(x, rval, ex, rerr);
 	  hadrons->addPoint(x, sig_h, ex, make_pair(err_h,err_h));
 	  muons  ->addPoint(x, sig_m, ex, make_pair(err_m,err_m));
 	}
 	else {
 	  mult   ->addPoint(x, 0., ex, make_pair(0.,.0));
 	  hadrons->addPoint(x, 0., ex, make_pair(0.,.0));
 	  muons  ->addPoint(x, 0., ex, make_pair(0.,.0));
 	}
       }
     }
 
     //@}
 
 
     /// @name Histograms
     //@{
     CounterPtr _c_hadrons, _c_muons;
     //@}
 
 
   };
 
 
   // The hook for the plugin system
   DECLARE_RIVET_PLUGIN(BESII_2009_I814778);
 
 
 }
diff --git a/analyses/pluginBES/BES_1995_I39870.cc b/analyses/pluginBES/BES_1995_I39870.cc
--- a/analyses/pluginBES/BES_1995_I39870.cc
+++ b/analyses/pluginBES/BES_1995_I39870.cc
@@ -1,88 +1,89 @@
 // -*- C++ -*-
 #include "Rivet/Analysis.hh"
 #include "Rivet/Projections/FinalState.hh"
 
 namespace Rivet {
 
 
   /// @brief Add a short analysis description here
   class BES_1995_I39870 : public Analysis {
   public:
 
     /// Constructor
     DEFAULT_RIVET_ANALYSIS_CTOR(BES_1995_I39870);
 
 
     /// @name Analysis methods
     //@{
 
     /// Book histograms and initialise projections before the run
     void init() {
       // Initialise and register projections
       declare(FinalState(), "FS");
 
       // Book histograms
-      _c_hadrons = bookCounter("/TMP/sigma_hadrons");
+      book(_c_hadrons, "/TMP/sigma_hadrons");
     }
 
 
     /// Perform the per-event analysis
     void analyze(const Event& event) {
       const FinalState& fs = apply<FinalState>(event, "FS");
 
       map<long,int> nCount;
       int ntotal(0);
-      foreach (const Particle& p, fs.particles()) {
-	nCount[p.pdgId()] += 1;
+      for (const Particle& p : fs.particles()) {
+	nCount[p.pid()] += 1;
 	++ntotal;
       }
       // mu+mu- + photons
       if(nCount[-13]==1 and nCount[13]==1 &&
 	 ntotal==2+nCount[22])
 	vetoEvent;
       // everything else
       else
-	_c_hadrons->fill(event.weight());
+	_c_hadrons->fill();
     }
 
 
     /// Normalise histograms etc., after the run
     void finalize() {
       double fact = crossSection()/ sumOfWeights() /nanobarn;
       double sig_h = _c_hadrons->val()*fact;
       double err_h = _c_hadrons->err()*fact;
       Scatter2D temphisto(refData(1, 1, 1));
-      Scatter2DPtr hadrons  = bookScatter2D(1, 1, 1);
+      Scatter2DPtr hadrons;
+      book(hadrons, 1, 1, 1);
       for (size_t b = 0; b < temphisto.numPoints(); b++) {
 	const double x  = temphisto.point(b).x();
 	pair<double,double> ex = temphisto.point(b).xErrs();
 	pair<double,double> ex2 = ex;
 	if(ex2.first ==0.) ex2. first=0.0001;
 	if(ex2.second==0.) ex2.second=0.0001;
 	if (inRange(sqrtS()/GeV, x-ex2.first, x+ex2.second)) {
 	  hadrons->addPoint(x, sig_h, ex, make_pair(err_h,err_h));
 	}
 	else {
 	  hadrons->addPoint(x, 0., ex, make_pair(0.,.0));
 	}
       }
 
     }
 
     //@}
 
 
     /// @name Histograms
     //@{
     CounterPtr _c_hadrons;
     //@}
 
 
   };
 
 
   // The hook for the plugin system
   DECLARE_RIVET_PLUGIN(BES_1995_I39870);
 
 
 }
diff --git a/include/Rivet/Event.hh b/include/Rivet/Event.hh
--- a/include/Rivet/Event.hh
+++ b/include/Rivet/Event.hh
@@ -1,221 +1,221 @@
 // -*- C++ -*-
 #ifndef RIVET_Event_HH
 #define RIVET_Event_HH
 
 #include "Rivet/Config/RivetCommon.hh"
 #include "Rivet/Particle.hh"
 #include "Rivet/Projection.hh"
 
 namespace Rivet {
 
 
   /// Rivet wrapper for HepMC event and Projection references.
   ///
   /// Event is a concrete class representing an generated event in Rivet. It is
   /// constructed given a HepMC::GenEvent, a pointer to which is kept by the
   /// Event object throughout its lifetime. The user must therefore make sure
   /// that the corresponding HepMC::GenEvent will persist at least as long as
   /// the Event object.
   ///
   /// In addition to the HepMC::GenEvent object the Event also keeps track of
   /// all Projection objects which have been applied to the Event so far.
   class Event {
   public:
 
     /// @name Constructors and destructors.
     //@{
 
     /// Constructor from a HepMC GenEvent pointer
     Event(const GenEvent* ge, bool strip = false)
       : _genevent_original(ge) {
       assert(ge);
       _genevent = *ge;
       if ( strip ) _strip(_genevent);
       _init(*ge);
     }
 
     /// Constructor from a HepMC GenEvent reference
     /// @deprecated HepMC uses pointers, so we should talk to HepMC via pointers
     Event(const GenEvent& ge, bool strip = false)
       : _genevent_original(&ge), _genevent(ge) {
         if ( strip ) _strip(_genevent);
         _init(ge);
       }
 
     /// Copy constructor
     Event(const Event& e)
       : _genevent_original(e._genevent_original), _genevent(e._genevent)
     {  }
 
     //@}
 
 
     /// @name Major event properties
     //@{
 
     /// The generated event obtained from an external event generator
     const GenEvent* genEvent() const { return &_genevent; }
 
     /// The generated event obtained from an external event generator
     const GenEvent* originalGenEvent() const { return _genevent_original; }
 
     /// Get the beam particles
     ParticlePair beams() const;
 
     /// Get the beam centre-of-mass energy
     double sqrtS() const;
 
     /// Get the beam centre-of-mass energy per nucleon
     double asqrtS() const;
 
     /// Get the generator centrality (impact-parameter quantile in [0,1]; or -1 if undefined (usual for non-HI generators))
     //double centrality() const;
 
     // /// Get the boost to the beam centre-of-mass
     // Vector3 beamCMSBoost() const;
 
     // /// Get the boost to the beam centre-of-mass
     // LorentzTransform beamCMSTransform();
 
     //@}
 
 
     /// @name Access to event particles
     //@{
 
     /// All the raw GenEvent particles, wrapped in Rivet::Particle objects
     const Particles& allParticles() const;
 
     /// @brief All the raw GenEvent particles, wrapped in Rivet::Particle objects, but with a Cut applied
     ///
     /// @note Due to the cut, this returns by value, i.e. involves an expensive copy
     inline Particles allParticles(const Cut& c) const {
       return filter_select(allParticles(), c);
     }
 
     /// @brief All the raw GenEvent particles, wrapped in Rivet::Particle objects, but with a selection function applied
     ///
     /// @note Due to the cut, this returns by value, i.e. involves an expensive copy
     template <typename FN>
     inline Particles allParticles(const FN& f) const {
       return filter_select(allParticles(), f);
     }
 
     /// @brief The generation weight associated with the event
     ///
     /// @todo This needs to be revisited when we finally add the mechanism to
     /// support NLO counter-events and weight vectors.
     std::valarray<double> weights() const;
 
     /// @brief Obsolete weight method. Always returns 1 now.
     DEPRECATED("Event weight does not need to be included anymore. For compatibility, it's always == 1 now.")
     double weight() const { return 1.0; }
     //@}
 
 
     /// @name Projection running
     //@{
 
     /// @brief Add a projection @a p to this Event.
     ///
     /// If an equivalent Projection has been applied before, the
     /// Projection::project(const Event&) of @a p is not called and a reference
     /// to the previous equivalent projection is returned. If no previous
     /// Projection was found, the Projection::project(const Event&) of @a p is
     /// called and a reference to @a p is returned.
     ///
     /// @todo Can make this non-templated, since only cares about ptr to Projection base class
     ///
     /// @note Comparisons here are by direct pointer comparison, because
     /// equivalence is guaranteed if pointers are equal, and inequivalence
     /// guaranteed if they aren't, thanks to the ProjectionHandler registry
     template <typename PROJ>
     const PROJ& applyProjection(PROJ& p) const {
       Log& log = Log::getLog("Rivet.Event");
       static bool docaching = getEnvParam("RIVET_CACHE_PROJECTIONS", true);
       if (docaching) {
-        log << Log::TRACE << "Applying projection " << &p << " (" << p.name() << ") -> comparing to projections " << _projections << endl;
+        log << Log::TRACE << "Applying projection " << &p << " (" << p.name() << ") -> comparing to projections " << _projections << std::endl;
         // First search for this projection *or an equivalent* in the already-executed list
         const Projection* cpp(&p);
         /// @note Currently using reint cast to integer type to bypass operator==(Proj*, Proj*)
         // std::set<const Projection*>::const_iterator old = _projections.find(cpp);
         std::set<const Projection*>::const_iterator old = std::begin(_projections);
         std::uintptr_t recpp = reinterpret_cast<std::uintptr_t>(cpp);
         for (; old != _projections.end(); ++old)
           if (reinterpret_cast<std::uintptr_t>(*old) == recpp) break;
         if (old != _projections.end()) {
-          log << Log::TRACE << "Equivalent projection found -> returning already-run projection " << *old << endl;
+          log << Log::TRACE << "Equivalent projection found -> returning already-run projection " << *old << std::endl;
           const Projection& pRef = **old;
           return pcast<PROJ>(pRef);
         }
-        log << Log::TRACE << "No equivalent projection in the already-run list -> projecting now" << endl;
+        log << Log::TRACE << "No equivalent projection in the already-run list -> projecting now" << std::endl;
       } else {
-        log << Log::TRACE << "Applying projection " << &p << " (" << p.name() << ") WITHOUT projection caching & comparison" << endl;
+        log << Log::TRACE << "Applying projection " << &p << " (" << p.name() << ") WITHOUT projection caching & comparison" << std::endl;
       }
       // If this one hasn't been run yet on this event, run it and add to the list
       Projection* pp = const_cast<Projection*>(&p);
       pp->_isValid = true;
       pp->project(*this);
       if (docaching) _projections.insert(pp);
       return p;
     }
 
 
     /// @brief Add a projection @a p to this Event by pointer.
     template <typename PROJ>
     const PROJ& applyProjection(PROJ* pp) const {
       if (!pp) throw Error("Event::applyProjection(PROJ*): Projection pointer is null.");
       return applyProjection(*pp);
     }
 
     //@}
 
 
   private:
 
     /// @brief Actual (shared) implementation of the constructors from GenEvents
     void _init(const GenEvent& ge);
 
     /// @brief Remove uninteresting or unphysical particles in the
     /// GenEvent to speed up searches.
     void _strip(GenEvent & ge);
 
     // /// @brief Convert the GenEvent to use conventional alignment
     // ///
     // /// For example, FHerwig only produces DIS events in the unconventional
     // /// hadron-lepton orientation and has to be corrected for DIS analysis
     // /// portability.
     // void _geNormAlignment();
 
     /// @brief The generated event, as obtained from an external generator.
     ///
     /// This is the original GenEvent. In practise the version seen by users
     /// will often/always be a modified one.
     ///
     /// @todo Provide access to this via an Event::originalGenEvent() method? If requested...
     const GenEvent* _genevent_original;
 
     /// @brief The GenEvent used by Rivet analysis projections etc.
     ///
     /// This version may be rotated to a "normal" alignment, have
     /// generator-specific particles stripped out, etc.  If an analysis is
     /// affected by these modifications, it is probably an unphysical analysis!
     ///
     /// Stored as a non-pointer since it may get overwritten, and memory for
     /// copying and cleanup is neater this way.
     /// @todo Change needed for HepMC3?
     mutable GenEvent _genevent;
 
     /// All the GenEvent particles, wrapped as Rivet::Particles
     /// @note To be populated lazily, hence mutability
     mutable Particles _particles;
 
     /// The set of Projection objects applied so far
     mutable std::set<ConstProjectionPtr> _projections;
 
   };
 
 
 }
 
 #endif
diff --git a/include/Rivet/Projections/AliceCommon.hh b/include/Rivet/Projections/AliceCommon.hh
--- a/include/Rivet/Projections/AliceCommon.hh
+++ b/include/Rivet/Projections/AliceCommon.hh
@@ -1,347 +1,347 @@
 #ifndef PROJECTIONS_ALICECOMMON_HH
 #define PROJECTIONS_ALICECOMMON_HH
 #include "Rivet/Tools/AliceCommon.hh"
 #include "Rivet/Projections/FinalState.hh"
 #include "Rivet/Projections/SingleValueProjection.hh"
 #include "Rivet/Projections/TriggerProjection.hh"
 #include "Rivet/Projections/PrimaryParticles.hh"
 
 namespace Rivet {
   namespace ALICE {
 
     /// @todo We should avoid experiment-specific projections and tools as much as possible...
     /// Says Leif: on the contrary this is a good thing!
 
 
     /// Template for ALICE V0 multiplicity projection.   Which
     /// acceptance to look in depends on the template argument @a MODE:
     ///
     /// - @c MODE=-1  Check the V0-C acceptance (@f$-3.7<\eta<-1.7@f$)
     /// - @c MODE=+1  Check the V0-A acceptance (@f$+2.8<\eta<+5.1@f$)
     /// - @c MODE=0   Check both V0-A and -C acceptances (sum)
     ///
     /// @ingroup alice_rivet
     template <int MODE>
     class V0Multiplicity : public SingleValueProjection {
     public:
       V0Multiplicity() : SingleValueProjection() {
         setName("ALICE::V0Multiplicity");
         Cut cut;
         if      (MODE < 0) cut = V0Cacceptance;
         else if (MODE > 0) cut = V0Aacceptance;
         else               cut = (V0Aacceptance || V0Cacceptance);
         // Declare our projection.  Note, the cuts stipulate charged
         // particles, so we just use a final state (rather than
         // charged-final state) projection here.
         const FinalState fs(cut);
         this->declare(fs, "FinalState");
       }
 
       /// Destructor
       virtual ~V0Multiplicity() {}
 
       /// Do the projection.  Sums number of charged final state
       /// particles within the acceptances of the specified V0
       /// sub-detectors.
       ///
       /// @param e Event to project from
       virtual void project(const Event& e) {
         clear();
         set(apply<FinalState>(e,"FinalState").particles().size());
       }
 
       /// Clone this projection
       ///
       /// @return New wrapped pointer to object of this class
       virtual std::unique_ptr<Rivet::Projection> clone() const {
         return std::unique_ptr<Projection>(new V0Multiplicity<MODE>(*this));
       }
       /// Compare to another projection
       ///
       /// @param p Projection to compare against
       virtual CmpState compare(const Projection& p) const {
 	return dynamic_cast<const V0Multiplicity<MODE>*>(&p) ?
 	  CmpState::EQ : CmpState::NEQ;
       }
 
     };
 
     /// Convenience typedef for A-side multiplicity
     ///
     /// @ingroup alice_rivet
     typedef V0Multiplicity<-1> V0AMultiplicity;
 
     /// Convenience typedef for C-side multiplicity
     ///
     /// @ingroup alice_rivet
     typedef V0Multiplicity<+1> V0CMultiplicity;
 
     /// Convenience typedef for A & C multiplicity
     ///
     /// @ingroup alice_rivet
     typedef V0Multiplicity<0> V0MMultiplicity;
 
 
 
     /// Template for ALICE CL multiplicity projection.  Which
     /// acceptance to look in depends on the template argument @a INNER:
     ///
     /// - @c INNER=true Check the inner SPD layer
     /// - @c INNER=false  Check the outer SPD layer
     ///
     /// @ingroup alice_rivet
     template <bool INNER>
     class CLMultiplicity : public SingleValueProjection {
     public:
 
       /// Constructor
       CLMultiplicity() : SingleValueProjection() {
         setName("ALICE::CLMultiplicity");
         Cut cut;
         if   (INNER) cut = CL0acceptance;
         else         cut = CL1acceptance;
         // Declare our projection.  Note, the cuts stipulate charged
         // particles, so we just use a final state (rather than
         // charged-final state) projection here.
         const FinalState fs(cut);
         this->declare(fs, "FinalState");
       }
 
       /// Destructor
       virtual ~CLMultiplicity() {}
 
       /// Do the projection.  Sums number of charged final state
       /// particles within the acceptances of the specified CL
       /// sub-detectors.
       ///
       /// @param e Event to project from
       virtual void project(const Event& e) {
         clear();
         set(apply<FinalState>(e,"FinalState").particles().size());
       }
 
       /// Clone this projection
       ///
       /// @return New wrapped pointer to object of this class
       virtual std::unique_ptr<Rivet::Projection> clone() const {
         return std::unique_ptr<Projection>(new CLMultiplicity<INNER>(*this));
       }
 
       /// Compare to another projection
       ///
       /// @param p Projection to compare against
       virtual CmpState compare(const Projection& p) const {
 	return dynamic_cast<const CLMultiplicity<INNER>*>(&p) ?
 	  CmpState::EQ : CmpState::NEQ;
       }
 
     };
 
 
     /// Convenience typedef for inside-CL multiplicity
     ///
     /// @ingroup alice_rivet
     typedef CLMultiplicity<true>  CL0Multiplicity;
 
     /// Convenience typedef for outside-CL multiplicity
     ///
     /// @ingroup alice_rivet
     typedef CLMultiplicity<false> CL1Multiplicity;
 
 
 
      /// A template of ALICE V0-based triggers.
      ///
      /// - @c MODE=-1  Check in the V0-C acceptance (@f$-3.7<\eta<-1.7@f$)
      /// - @c MODE=+1  Check in the V0-A acceptance (@f$+2.8<\eta<+5.1@f$)
      /// - @c MODE=0   Check in both V0-A and -C acceptances (V0-OR)
      ///
      /// @ingroup alice_rivet
     template <int MODE>
     class V0Trigger : public TriggerProjection {
     public:
 
       /// Constructor
       V0Trigger() : TriggerProjection() {
         setName("ALICE::V0Trigger");
         // Declare our projection.  Note, the cuts stipulate charged
         // particles, so we just use a final state (rather than
         // charged-final state) projection here.
         const V0Multiplicity<MODE> fs;
         this->declare(fs, "FinalState");
       }
 
       /// Destructor
       virtual ~V0Trigger() {}
 
        /// Do the projection.  Checks if the number of projected
        /// particles is larger than 0
        ///
        /// @param e Event to project from
       virtual void project(const Event& e) {
         fail(); // Assume failure
         if (apply<V0Multiplicity<MODE>>(e, "FinalState")() > 0) pass();
       }
 
       /// Clone this projection
       ///
       /// @return New wrapped pointer to object of this class
       virtual std::unique_ptr<Rivet::Projection> clone() const {
         return std::unique_ptr<Projection>(new V0Trigger<MODE>(*this));
       }
 
       /// Compare to projections.
       ///
       /// @param p Projection to compare to.
       ///
       /// @return true (EQUIVALENT) if the projection @a p is of the same
       /// type as this.
       virtual CmpState compare(const Projection& p) const {
 	return dynamic_cast<const V0Trigger<MODE>*>(&p) ?
 	  CmpState::EQ : CmpState::NEQ;
       }
 
     };
 
     /// Convenience typedef for V0 A trigger
     ///
     /// @ingroup alice_rivet
     using V0ATrigger = V0Trigger<-1>;
 
     /// Convenience typedef for V0 C trigger
     ///
     /// @ingroup alice_rivet
     using V0CTrigger = V0Trigger<+1>;
 
     /// Convenience typedef for V0 A-or-C trigger
     ///
     /// @ingroup alice_rivet
     using V0OrTrigger = V0Trigger<0>;
 
 
 
     /// Trigger projection for the ALICE V0-AND (a.k.a. CINT7) requirement
     class V0AndTrigger : public TriggerProjection {
     public:
 
       /// Constructor
       V0AndTrigger() : TriggerProjection() {
         const V0ATrigger v0a;
         const V0CTrigger v0c;
         this->declare(v0a, "V0A");
         this->declare(v0c, "V0C");
       }
 
       /// Destructor
       virtual ~V0AndTrigger() {}
 
        /// Do the projection.  Checks if the numbers of projected
        /// particles on both sides, are larger than 0
        ///
        /// @param e Event to project from
       virtual void project(const Event& e) {
         fail(); // Assume failure
         if (apply<V0ATrigger>(e,"V0A")() && apply<V0CTrigger>(e,"V0C")()) pass();
       }
 
       /// Compare to projections.
       ///
       /// @param p Projection to compare to.
       virtual CmpState compare(const Projection& p) const
       {
 	return dynamic_cast<const V0AndTrigger*>(&p) ?
 	  CmpState::EQ : CmpState::NEQ;
       }
 
        /// Clone this projection
        ///
        /// @return New wrapped pointer to object of this class
       virtual std::unique_ptr<Rivet::Projection> clone() const {
         return std::unique_ptr<Projection>(new V0AndTrigger(*this));
       }
 
     };
 
 
     /// @brief Standard ALICE primary particle definition
     ///
     /// Primary particle definition according to public note
     /// <a href="https://cds.cern.ch/record/2270008">ALICE-PUBLIC-2017-005</a>
     ///
     /// @ingroup alice_rivet
     class PrimaryParticles : public Rivet::PrimaryParticles {
     public:
 
       PrimaryParticles(const Cut& c=Cuts::open())
         : Rivet::PrimaryParticles({},c)
       { }
 
        /// Compare to projections.
        ///
        /// @param p Projection to compare to.
        ///
        /// @return true (EQUIVALENT) if the projection @a p is of the same
        /// type as this, if the cuts are equal, and that the list of PDG
        /// IDs are the same.
       virtual CmpState compare(const Projection& p) const {
 	const PrimaryParticles* o = dynamic_cast<const PrimaryParticles*>(&p);
 	if (_cuts != o->_cuts) return CmpState::NEQ;
 	return mkPCmp(*o,"PrimaryParticles");
       }
 
       /// Clone this projection
       virtual std::unique_ptr<Rivet::Projection> clone() const {
         return std::unique_ptr<Projection>(new PrimaryParticles(*this));
       }
 
     protected:
 
        /// Check PDG ID of particle @a p is in the list of accepted
        /// primaries.
        ///
        /// @param p Particle to investigate.
        ///
        /// @return true if the particle PDG ID is in the list of known
        /// primary PDG IDs.
        ///
        /// @note We explicitly override this to allow for nuclei, and we
        /// explicitly check for a specific set of particles (and
        /// anti-particles).  This means we do not use the base class
        /// list of particles.  Therefore, we also need to override the
        /// compare method.
        bool isPrimaryPID(ConstGenParticlePtr p) const {
-        const int pdg = PID::abspid(p->pdg_id());
+        const int pdg = abs(p->pdg_id());
         // Check for nucleus
         if (pdg > 1000000000) return true;
 
         switch (pdg) {
         case Rivet::PID::MUON:
         case Rivet::PID::ELECTRON:
         case Rivet::PID::GAMMA:
         case Rivet::PID::PIPLUS:
         case Rivet::PID::KPLUS:
         case Rivet::PID::K0S:
         case Rivet::PID::K0L:
         case Rivet::PID::PROTON:
         case Rivet::PID::NEUTRON:
         case Rivet::PID::LAMBDA:
         case Rivet::PID::SIGMAMINUS:
         case Rivet::PID::SIGMAPLUS:
         case Rivet::PID::XIMINUS:
         case Rivet::PID::XI0:
         case Rivet::PID::OMEGAMINUS:
         case Rivet::PID::NU_E:
         case Rivet::PID::NU_MU:
         case Rivet::PID::NU_TAU:
           return true;
         }
         return false;
       }
 
     };
 
 
   }
 }
 
 #endif
diff --git a/include/Rivet/Projections/DISDiffHadron.hh b/include/Rivet/Projections/DISDiffHadron.hh
--- a/include/Rivet/Projections/DISDiffHadron.hh
+++ b/include/Rivet/Projections/DISDiffHadron.hh
@@ -1,64 +1,64 @@
 // -*- C++ -*-
 #ifndef RIVET_DISDiffHadron_HH
 #define RIVET_DISDiffHadron_HH
 
 #include "Rivet/Projections/Beam.hh"
 #include "Rivet/Projections/HadronicFinalState.hh"
 #include "Rivet/Particle.hh"
 #include "Rivet/Event.hh"
 
 namespace Rivet {
 
 
   /// @brief Get the incoming and outgoing hadron in a diffractive ep
   /// event.
   class DISDiffHadron : public Projection {
   public:
 
     /// @name Constructors.
     //@{
 
     /// Default constructor.
     DISDiffHadron() {
       setName("DISDiffHadron");
-      addProjection(Beam(), "Beam");
-      addProjection(FinalState(), "FS");
+      declare(Beam(), "Beam");
+      declare(FinalState(), "FS");
     }
 
     /// Clone on the heap.
     DEFAULT_RIVET_PROJ_CLONE(DISDiffHadron);
 
     //@}
 
 
   protected:
 
     /// Perform the projection operation on the supplied event.
     virtual void project(const Event& e);
 
     /// Compare with other projections.
-    virtual int compare(const Projection& p) const;
+    virtual CmpState compare(const Projection& p) const;
 
 
   public:
 
     /// The incoming lepton
     const Particle& in() const { return _incoming; }
 
     /// The outgoing lepton
     const Particle& out() const { return _outgoing; }
 
   private:
 
     /// The incoming lepton
     Particle _incoming;
 
     /// The outgoing lepton
     Particle _outgoing;
 
   };
 
 }
 
 
 #endif
diff --git a/include/Rivet/Projections/DISLepton.hh b/include/Rivet/Projections/DISLepton.hh
--- a/include/Rivet/Projections/DISLepton.hh
+++ b/include/Rivet/Projections/DISLepton.hh
@@ -1,120 +1,120 @@
 // -*- C++ -*-
 #ifndef RIVET_DISLepton_HH
 #define RIVET_DISLepton_HH
 
 #include "Rivet/Projections/Beam.hh"
 #include "Rivet/Projections/PromptFinalState.hh"
 #include "Rivet/Projections/HadronicFinalState.hh"
 #include "Rivet/Projections/DressedLeptons.hh"
 #include "Rivet/Projections/UndressBeamLeptons.hh"
 #include "Rivet/Particle.hh"
 #include "Rivet/Event.hh"
 
 namespace Rivet {
 
 
   /// @brief Get the incoming and outgoing leptons in a DIS event.
   class DISLepton : public Projection {
   public:
 
     /// Enum to enable different orderings for selecting scattered
     /// leptons in case several were found.
     enum SortOrder { ENERGY, ETA, ET };
     
     /// @name Constructors.
     //@{
 
     /// Default constructor taking general options. The recognised
     /// options are: LMODE, taking the options "prompt", "any" and
     /// "dressed"; DressedDR giving a delta-R cone radius where photon
     /// momenta are added to the lepton candidates for LMODE=dresses;
     /// IsolDR giving a cone in delta-R where no hadrons are allowed
     /// around a lepton candidate; and Undress giving a cone around
     /// the incoming incoming beam in which photons are considered
     /// initial state rafiation for which the momentum is subtracted
     /// from the beam momentum.
     DISLepton(const std::map<std::string,std::string> & opts =
               std::map<std::string,std::string>())
       : _isolDR(0.0), _sort(ENERGY) {
       setName("DISLepton");
-      addProjection(HadronicFinalState(), "IFS");
+      declare(HadronicFinalState(), "IFS");
 
       auto sorting = opts.find("LSort");
       if ( sorting != opts.end() && sorting->second == "ETA" )
         _sort = ETA;
       else if ( sorting != opts.end() && sorting->second == "ET" )
         _sort = ET;
 
       double undresstheta = 0.0;
       auto undress = opts.find("Undress");
       if ( undress != opts.end() )
         undresstheta = std::stod(undress->second);
       if ( undresstheta > 0.0 )
-        addProjection(UndressBeamLeptons(undresstheta), "Beam");
+        declare(UndressBeamLeptons(undresstheta), "Beam");
       else
-        addProjection(Beam(), "Beam");
+        declare(Beam(), "Beam");
 
       auto isol = opts.find("IsolDR");
       if ( isol != opts.end() ) _isolDR = std::stod(isol->second);
 
       double dressdr = 0.0;
       auto dress = opts.find("DressDR");
       if ( dress != opts.end() )
         dressdr = std::stod(dress->second);
 
       auto lmode = opts.find("LMode");
       if ( lmode != opts.end() && lmode->second == "any" )
-        addProjection(FinalState(), "LFS");
+        declare(FinalState(), "LFS");
       else if ( lmode != opts.end() && lmode->second == "dressed" )
-        addProjection(DressedLeptons(dressdr), "LFS");
+        declare(DressedLeptons(dressdr), "LFS");
       else
-        addProjection(PromptFinalState(), "LFS");
+        declare(PromptFinalState(), "LFS");
     }
 
     /// Clone on the heap.
     DEFAULT_RIVET_PROJ_CLONE(DISLepton);
 
     //@}
 
 
   protected:
 
     /// Perform the projection operation on the supplied event.
     virtual void project(const Event& e);
 
     /// Compare with other projections.
     virtual CmpState compare(const Projection& p) const;
 
 
   public:
 
     /// The incoming lepton
     const Particle& in() const { return _incoming; }
 
     /// The outgoing lepton
     const Particle& out() const { return _outgoing; }
 
     /// Sign of the incoming lepton pz component
     int pzSign() const { return sign(_incoming.pz()); }
 
 
   private:
 
     /// The incoming lepton
     Particle _incoming;
 
     /// The outgoing lepton
     Particle _outgoing;
 
     /// If larger than zerp an isolation cut around the lepton is required.
     double _isolDR;
 
     /// How to sort leptons
     SortOrder _sort;
 
   };
 
 }
 
 
 #endif
diff --git a/include/Rivet/Projections/DISRapidityGap.hh b/include/Rivet/Projections/DISRapidityGap.hh
--- a/include/Rivet/Projections/DISRapidityGap.hh
+++ b/include/Rivet/Projections/DISRapidityGap.hh
@@ -1,94 +1,94 @@
 // -*- C++ -*-
 #ifndef RIVET_DISRapidityGap_HH
 #define RIVET_DISRapidityGap_HH
 
 #include "Rivet/Projections/DISKinematics.hh"
 #include "Rivet/Projections/DISFinalState.hh"
 #include "Rivet/Particle.hh"
 #include "Rivet/Event.hh"
 
 namespace Rivet {
 
 
   /// @brief Get the incoming and outgoing hadron in a diffractive ep
   /// event.
   class DISRapidityGap : public Projection {
 
   public:
 
     /// Type of DIS boost to apply
     enum Frame { HCM, LAB, XCM };
 
     DISRapidityGap() {
       setName("DISRapidityGap");
-      addProjection(DISKinematics(), "DISKIN");
-      addProjection(DISFinalState(DISFinalState::HCM), "DISFS");
+      declare(DISKinematics(), "DISKIN");
+      declare(DISFinalState(DISFinalState::HCM), "DISFS");
     }
 
     DEFAULT_RIVET_PROJ_CLONE(DISRapidityGap);
 
     const double M2X()               const {return _M2X;}
     const double M2Y()               const {return _M2Y;}
     const double t()                 const {return _t;}
     const double gap()               const {return _gap;}
     const double gapUpp()            const {return _gapUpp;}
     const double gapLow()            const {return _gapLow;}
     const double EpPzX(Frame f) const {
       if (f == LAB) return _ePpzX_LAB;
       else if (f == XCM) return _ePpzX_XCM;
       else return _ePpzX_HCM;
     }
     const double EmPzX(Frame f) const {
       if (f == LAB) return _eMpzX_LAB;
       else if (f == XCM) return _eMpzX_XCM;
       else return _eMpzX_HCM;
     }
     const FourMomentum pX(Frame f) const {
       if (f == LAB) return _momX_LAB;
       else if (f == XCM) return _momX_XCM;
       else return _momX_HCM;
     }
     const FourMomentum pY(Frame f) const {
       if (f == LAB) return _momY_LAB;
       else if (f == XCM) return _momY_XCM;
       else return _momY_HCM;
     }
     const Particles& systemX(Frame f) const {
       if (f == LAB) return _pX_LAB;
       else if (f == XCM) return _pX_XCM;
       else return _pX_HCM;
     }
     const Particles& systemY(Frame f) const {
       if (f == LAB) return _pY_LAB;
       else if (f == XCM) return _pY_XCM;
       else return _pY_HCM;
     }
 
   protected:
 
-    virtual int compare(const Projection& p) const;
+    virtual CmpState compare(const Projection& p) const;
 
     virtual void project(const Event& e);
 
     void clearAll();
 
     void findgap(const Particles& particles, const DISKinematics& diskin);
 
   private:
 
     double _M2X, _M2Y, _t;
     double _gap, _gapUpp, _gapLow;
     double _ePpzX_LAB, _eMpzX_LAB;
     double _ePpzX_HCM, _eMpzX_HCM;
     double _ePpzX_XCM, _eMpzX_XCM;
     FourMomentum _momX_HCM, _momY_HCM;
     FourMomentum _momX_LAB, _momY_LAB;
     FourMomentum _momX_XCM, _momY_XCM;
     Particles _pX_HCM, _pY_HCM, _pX_LAB, _pY_LAB, _pX_XCM, _pY_XCM;
 
   };
 
 }
 
 
 #endif
diff --git a/include/Rivet/Projections/EventMixingFinalState.hh b/include/Rivet/Projections/EventMixingFinalState.hh
--- a/include/Rivet/Projections/EventMixingFinalState.hh
+++ b/include/Rivet/Projections/EventMixingFinalState.hh
@@ -1,228 +1,228 @@
 // -*- C++ -*-
 #ifndef RIVET_EventMixingFinalState_HH
 #define RIVET_EventMixingFinalState_HH
 
 #include "Rivet/Projection.hh"
 #include "Rivet/Projections/ParticleFinder.hh"
 #include "Rivet/Tools/Random.hh"
 #include <deque>
 #include <algorithm>
 
 namespace Rivet {
 
   // @brief Projects out an event mixed of several events, given
   // a mixing observable (eg. number of final state particles),
   // defining what should qualify as a mixable event.
   // Binning in the mixing observable is defined in the constructor,
   // as is the number of events one wants to mix with.
   // The method calculateMixingObs() must can be overloaded
   // in derived classes, to provide the definition of the mixing observable,
   // on the provided projection, eg. centrality or something more elaborate.
   //
   // The implementation can correcly handle mixing of weighted events, but
   // not multi-weighted events. Nor does the implementation attemt to handle
   // calculation of one (or more) event weights for the mixed events. For most
   // common use cases, like calculating a background sample, this is sufficient.
   // If a more elaborate use case ever turns up, this must be reevaluated.
   // 
   //
   // @author Christian Bierlich <christian.bierlich@thep.lu.se>
 
   // Weighted random shuffle, similar to std::random_shuffle, which
   // allows the passing of a weight for each element to be shuffled.
   template <class RandomAccessIterator, 
     class WeightIterator, class RandomNumberGenerator>
   void weighted_shuffle(RandomAccessIterator first, RandomAccessIterator last,
     WeightIterator fw, WeightIterator lw, RandomNumberGenerator& g) {
       while(first != last && fw != lw) {
 	std::discrete_distribution<int> weightDist(fw, lw);
         int i = weightDist(g);
         if(i){
 	  std::iter_swap(first, next(first, i));
 	  std::iter_swap(fw, next(fw, i));
         }
         ++first;
         ++fw;
       }
   }
   // A MixEvent is a vector of particles with and associated weight.
   typedef pair<Particles, double> MixEvent;
   typedef map<double, std::deque<MixEvent> > MixMap;	
 
   /// EventMixingBase is the base class for event mixing projections.
   ///
   /// Most methods are defined in this base class as they should.
   /// In order to use it, a derived class should be implemented where:
   /// - The constructor is reimplmented, giving the derived projection type
   /// from which the mixing observable is calculated. The constructor must also
   /// be declared public in the derived class.
   /// - The calculateMixingObs is implemented.
   /// To examples of such derived classes are given below,
   /// 1) EventMixingFinalState, where the mixing observable are calculated
   /// on a multiplicity of a charged final state, and:
   /// 2) EventMixingCentrality, where the mixing observable is centrality.
   ///
   class EventMixingBase : public Projection {
   protected:
     // Constructor
-    EventMixingBase(const Projection* mixObsProjPtr, const ParticleFinder& mix,
+    EventMixingBase(const Projection & mixObsProj, const ParticleFinder& mix,
       size_t nMixIn, double oMin, double oMax, double deltao) : nMix(nMixIn),
       unitWeights(true) {
       // The base class contructor should be called explicitly in derived classes
       // to add projections below.
       setName("EventMixingBase");
-      declare(*mixObsProjPtr,"OBS");
+      declare(mixObsProj,"OBS");
       declare(mix,"MIX");
       MSG_WARNING("EventMixing is not fully validated. Use with caution.");
 
       // Set up the map for mixing events.
       for(double o = oMin; o < oMax; o+=deltao )
         mixEvents[o] = std::deque<MixEvent>();
     }
 
   public:
   
     // Test if we have enough mixing events available for projected,
     // current mixing observable.
     bool hasMixingEvents() const {
       MixMap::const_iterator mixItr = mixEvents.lower_bound(mObs);
       if(mixItr == mixEvents.end() || mixItr->second.size() < nMix + 1)
         return false;
       return true;
     }
     
     // Return a vector of mixing events.
     vector<MixEvent> getMixingEvents() const {
       if (!hasMixingEvents())
         return vector<MixEvent>();
       MixMap::const_iterator mixItr = mixEvents.lower_bound(mObs);
       return vector<MixEvent>(mixItr->second.begin(), mixItr->second.end() - 1);
     }
 
     // Return a vector of particles from the mixing events. Can
     // be overloaded in derived classes, though normally not neccesary.
     virtual const Particles particles() const {
       // Test if we have enough mixing events.
       if(!hasMixingEvents()) 
 	return vector<Particle>();
       // Get mixing events for the current, projected mixing observable.
       MixMap::const_iterator mixItr = mixEvents.lower_bound(mObs);
       vector<MixEvent> mixEvents = 
         vector<MixEvent>(mixItr->second.begin(), mixItr->second.end() - 1);
       // Make the vector of mixed particles.
       Particles mixParticles;
       vector<double> weights;
       size_t pSize = 0;
       for(size_t i = 0; i < mixEvents.size(); ++i)
         pSize+=mixEvents[i].first.size();
       mixParticles.reserve(pSize);
       weights.reserve(pSize);
       // Put the particles in the vector.
       for(size_t i = 0; i < mixEvents.size(); ++i) {
         mixParticles.insert(mixParticles.end(), mixEvents[i].first.begin(), 
 	  mixEvents[i].first.end());
 	vector<double> tmp = vector<double>(mixEvents[i].first.size(),
 	  mixEvents[i].second);
         weights.insert(weights.end(), tmp.begin(), tmp.end());
       }
 
       // Shuffle the particles.
       if (unitWeights) {
         // Use the thread safe random number generator.
         auto rnd = [&] (int i) {return rng()()%i;};
         random_shuffle(mixParticles.begin(), mixParticles.end(), rnd);
 	return mixParticles;
       }
       else {
         weighted_shuffle(mixParticles.begin(), mixParticles.end(),
 	  weights.begin(), weights.end(), rng());
 	Particles tmp = vector<Particle>(mixParticles.begin(), 
 	  mixParticles.begin() + size_t(ceil(mixParticles.size() / 2)));
         return tmp;
       }
     }
 
   protected:
 
     // Calulate mixing observable.
     // Must be overloaded in derived classes.
     virtual void calculateMixingObs(const Projection* mProj) = 0;
     
     /// Perform the projection on the Event.
     void project(const Event& e){
       const Projection* mixObsProjPtr = &applyProjection<Projection>(e, "OBS");
       calculateMixingObs(mixObsProjPtr);
       MixMap::iterator mixItr = mixEvents.lower_bound(mObs);
       if(mixItr == mixEvents.end()){
         // We are out of bounds.
         MSG_DEBUG("Mixing observable out of bounds.");
         return;
       }
       const Particles mix = applyProjection<ParticleFinder>(e, "MIX").particles();
       mixItr->second.push_back(make_pair(mix,e.weights()[0]));
       // Assume unit weights until we see otherwise.
       if (unitWeights && e.weights()[0] != 1.0 ) {
         unitWeights = false;
 	nMix *= 2;
       }
       if(mixItr->second.size() > nMix + 1)
         mixItr->second.pop_front();
     }
 
     /// Compare with other projections
     CmpState compare(const Projection& p) const {
       return mkNamedPCmp(p,"OBS");
     }
     
     /// The mixing observable of the current event.
     double mObs;
   
   private:
 
     /// The number of event to mix with.
     size_t nMix;
     /// The event map.
     MixMap mixEvents;
     /// Using unit weights or not.
     bool unitWeights;
   };
 
   // EventMixingFinalState has multiplicity in the mixing projection.
   // as the mixing observable.
   class EventMixingFinalState : public EventMixingBase {
    public:
-    EventMixingFinalState(const ParticleFinder* mixObsProjPtr, 
+    EventMixingFinalState(const ParticleFinder & mixObsProj, 
       const ParticleFinder& mix, size_t nMixIn, double oMin, double oMax,
       double deltao) : 
-      EventMixingBase(mixObsProjPtr, mix, nMixIn, oMin, oMax, deltao) {
+      EventMixingBase(mixObsProj, mix, nMixIn, oMin, oMax, deltao) {
     	setName("EventMixingFinalState");
       }
 
     DEFAULT_RIVET_PROJ_CLONE(EventMixingFinalState);
    
    protected:
     // Calulate mixing observable.
     virtual void calculateMixingObs(const Projection* mProj) {
       mObs = ((ParticleFinder*) mProj)->particles().size();
     }
   };
 
   // EventMixingCentrality has centrality as the mixing observable.
   class EventMixingCentrality : public EventMixingBase {
     public:
-      EventMixingCentrality(const CentralityProjection* mixObsProjPtr,
+      EventMixingCentrality(const CentralityProjection& mixObsProj,
         const ParticleFinder& mix, size_t nMixIn, double oMin, double oMax,
        	double deltao) : 
-      EventMixingBase(mixObsProjPtr, mix, nMixIn, oMin, oMax, deltao) {
+      EventMixingBase(mixObsProj, mix, nMixIn, oMin, oMax, deltao) {
     	setName("EventMixingCentrality");
       }
     
       DEFAULT_RIVET_PROJ_CLONE(EventMixingCentrality);
     protected:
       virtual void calculateMixingObs(const Projection* mProj) {
         mObs = ((CentralityProjection*) mProj)->operator()();
       }
   }; 
 }
 
 #endif
diff --git a/include/Rivet/Projections/HepMCHeavyIon.hh b/include/Rivet/Projections/HepMCHeavyIon.hh
--- a/include/Rivet/Projections/HepMCHeavyIon.hh
+++ b/include/Rivet/Projections/HepMCHeavyIon.hh
@@ -1,180 +1,180 @@
 // -*- C++ -*-
 #ifndef RIVET_HepMCHeavyIon_HH
 #define RIVET_HepMCHeavyIon_HH
 
 #include "Rivet/Projection.hh"
 #include "Rivet/Tools/RivetHepMC.hh"
 #include "Rivet/Event.hh"
 
 namespace Rivet {
 
 
   class HepMCHeavyIon : public Projection {
   public:
 
     /// @name Constructors etc.
     //@{
 
     /// Constructor
     HepMCHeavyIon();
 
     /// Clone on the heap.
     DEFAULT_RIVET_PROJ_CLONE(HepMCHeavyIon);
 
     //@}
 
 
   protected:
 
     /// Perform the projection on the Event
     void project(const Event& e);
 
     /// Compare with other projections
     //int compare(const Projection& p) const;
     // Taken from Thrust.hh
-    int compare(const Projection& p) const {
-      return 0;
+    CmpState compare(const Projection& p) const {
+      return CmpState::EQ;
     }
 
   public:
 
     /// Check that there were at all any heavy ion info in HepMC
     bool ok() const { return _hi != nullptr; }
 
     /// @brief the number of hard nucleon-nucleon collisions.
     ///
     /// Model-dependent. Usually the number of nucleon-nucleon
     /// collisions containing a special signal process. A negative
     /// value means that the information is not available.
     int    Ncoll_hard() const;
     
     /// @brief the number of participating nucleons in the projectile.
     ///
     /// The number of nucleons in the projectile participating in an
     /// inelastic collision (see Ncoll). A negative value means that
     /// the information is not available.
     int    Npart_proj() const;
     
     /// @brief the number of participating nucleons in the target.
     ///
     /// The number of nucleons in the target participating in an
     /// inelastic collision (see Ncoll). A negative value means that
     /// the information is not available.
     int    Npart_targ() const;
 
     /// @brief the number of inelastic nucleon-nucleon collisions.
     ///
     /// Note that a one participating nucleon can be involved in many
     /// inelastic collisions, and that inelastic also includes
     /// diffractive excitation. A negative value means that the
     /// information is not available.
     /// 
     int    Ncoll() const;
     /// @brief Collisions with a diffractively excited target nucleon.
     ///
     /// The number of single diffractive nucleon-nucleon collisions
     /// where the target nucleon is excited. A negative value means
     /// that the information is not available.
     int    N_Nwounded_collisions() const;
     
     /// @brief Collisions with a diffractively excited projectile nucleon.
     ///
     /// The number of single diffractive nucleon-nucleon collisions
     /// where the projectile nucleon is excited. A negative value
     /// means that the information is not available.
     int    Nwounded_N_collisions() const;
 
     /// @brief Non-diffractive or doubly diffractive collisions.
     ///
     /// The number of nucleon-nucleon collisions where both projectile
     /// and target nucleons are wounded. A negative value means that
     /// the information is not available.
     int    Nwounded_Nwounded_collisions() const;
 
     /// @brief The impact parameter.
     ///
     /// The impact parameter given in units of femtometer. A negative
     /// value means that the information is not available.
     double impact_parameter() const;
 
     /// @brief The event plane angle.
     ///
     /// The angle wrt. the x-axix of the impact parameter vector
     /// (pointing frm the target to the projectile). A positive number
     /// between 0 and two pi. A negative value means that the
     /// information is not available.
     double event_plane_angle() const;
     /// @brief The assumed inelastic nucleon-nucleon cross section
     ///
     /// in units of millibarn. As used in a Glauber calculation to
     /// simulate the distribution in Ncoll. A negative value means
     /// that the information is not available.
     double sigma_inel_NN() const;
 
     /// @brief The centrality.
     ///
     /// The generated centrality in percentiles, where 0 is the
     /// maximally central and 100 is the minimally central. A negative
     /// value means that the information is not available.
     double centrality() const;
 
     /// @brief A user defined centrality estimator.
     ///
     /// This variable may contain anything a generator feels is
     /// reasonable for estimating centrality. The value should be
     /// non-negative, and a low value corresponds to a low
     /// centrality. A negative value indicatess that the information
     /// is not available.
     double user_cent_estimate() const;
 
     /// @brief The number of spectator neutrons in the projectile
     ///
     /// ie. those that thave not participated in any inelastic
     /// nucleon-nucleon collision. A negative value indicatess that
     /// the information is not available.
     int Nspec_proj_n() const;
 
     /// @brief The number of spectator neutrons in the target
     ///
     /// ie. those that thave not participated in any inelastic
     /// nucleon-nucleon collision. A negative value indicatess that
     /// the information is not available.
     int Nspec_targ_n() const;
 
     /// @brief The number of spectator protons in the projectile
     ///
     /// ie. those that thave not participated in any inelastic
     /// nucleon-nucleon collision. A negative value indicatess that
     /// the information is not available.
     int Nspec_proj_p() const;
 
     /// @brief The number of spectator protons in the target
     ///
     /// ie. those that thave not participated in any inelastic
     /// nucleon-nucleon collision. A negative value indicatess that
     /// the information is not available.
     int Nspec_targ_p() const;
 
     /// @brief Participant plane angles
     ///
     /// calculated to different orders. The key of the map specifies
     /// the order, and the value gives to the angle wrt. the
     /// event plane.
     map<int,double> participant_plane_angles() const;
 
     /// @brief Eccentricities
     ///
     /// Calculated to different orders. The key of the map specifies
     /// the order, and the value gives the corresponding eccentricity.
     map<int,double> eccentricities() const;
 
   private:
 
     /// A pointer to the actual heavy ion object
     ConstGenHeavyIonPtr _hi;
 
   };
 }
 
 
 #endif
diff --git a/include/Rivet/Projections/UndressBeamLeptons.hh b/include/Rivet/Projections/UndressBeamLeptons.hh
--- a/include/Rivet/Projections/UndressBeamLeptons.hh
+++ b/include/Rivet/Projections/UndressBeamLeptons.hh
@@ -1,46 +1,46 @@
 // -*- C++ -*-
 #ifndef RIVET_UndressBeamLeptons_HH
 #define RIVET_UndressBeamLeptons_HH
 
 #include "Rivet/Projections/Beam.hh"
 #include "Rivet/Projections/FinalState.hh"
 
 namespace Rivet {
 
 
   /// @brief Project out the incoming beams, but subtract any colinear
   /// photons from lepton beams within a given cone.
   class UndressBeamLeptons : public Beam {
   public:
 
     /// Default (and only) constructor. Takes an angle as
     /// argument. The momentum of any photon within This angle wrt. a
     /// charged lepton beam will be subtracted from the beam lepton
     /// momentum.
     UndressBeamLeptons(double theta = 0.0): _thetamax(theta) {
       setName("UndressBeamLeptons");
-      addProjection(FinalState(), "FS");
+      declare(FinalState(), "FS");
     }
 
     /// Clone on the heap
     DEFAULT_RIVET_PROJ_CLONE(UndressBeamLeptons);
 
 
     /// Project on to the Event
     virtual void project(const Event& e);
 
 
   private:
 
     /// Compare with other projections.
-    virtual int compare(const Projection & p) const;
+    virtual CmpState compare(const Projection & p) const;
 
     /// The beam particles in the current collision
     double _thetamax;
 
   };
 
 
 }
 
 #endif
diff --git a/include/Rivet/Tools/RivetHepMC.hh b/include/Rivet/Tools/RivetHepMC.hh
--- a/include/Rivet/Tools/RivetHepMC.hh
+++ b/include/Rivet/Tools/RivetHepMC.hh
@@ -1,169 +1,100 @@
 // -*- C++ -*-
 #ifndef RIVET_RivetHepMC_HH
 #define RIVET_RivetHepMC_HH
 
 #ifdef ENABLE_HEPMC_3
 #include "HepMC3/HepMC3.h"
 #include "HepMC3/Relatives.h"
 #include "HepMC3/Reader.h"
 
 namespace Rivet{
   namespace RivetHepMC = HepMC3;
   using RivetHepMC::ConstGenParticlePtr;
   using RivetHepMC::ConstGenVertexPtr;
   using RivetHepMC::Relatives;
   using RivetHepMC::ConstGenHeavyIonPtr;
   
   using HepMC_IO_type = RivetHepMC::Reader;
 
   using PdfInfo = RivetHepMC::GenPdfInfo;
 }
 
 #else
 #include "HepMC/GenEvent.h"
 #include "HepMC/GenParticle.h"
 #include "HepMC/HeavyIon.h"
 #include "HepMC/GenVertex.h"
 #include "HepMC/Version.h"
 #include "HepMC/GenRanges.h"
 #include "HepMC/IO_GenEvent.h"
 
 namespace Rivet{
   namespace RivetHepMC = HepMC;
 
   
   // HepMC 2.07 provides its own #defines
   typedef const HepMC::GenParticle* ConstGenParticlePtr;
   typedef const HepMC::GenVertex* ConstGenVertexPtr;
   typedef const HepMC::HeavyIon* ConstGenHeavyIonPtr;
   
   /// @brief Replicated the HepMC3 Relatives syntax using HepMC2 IteratorRanges
   /// This is necessary mainly because of capitalisation differences
   class Relatives{
     
     public:
     
     constexpr Relatives(HepMC::IteratorRange relo): _internal(relo){}
     
     constexpr HepMC::IteratorRange operator()() const {return _internal;}
     operator HepMC::IteratorRange() const {return _internal;}
     
     const static Relatives PARENTS;
     const static Relatives CHILDREN;
     const static Relatives ANCESTORS;
     const static Relatives DESCENDANTS;
     
     private:
     const HepMC::IteratorRange _internal;
     
   };
   
   using HepMC_IO_type = HepMC::IO_GenEvent;
   using PdfInfo = RivetHepMC::PdfInfo;
 
 }
   
 #endif
 
 #include "Rivet/Tools/RivetSTL.hh"
 #include "Rivet/Tools/Exceptions.hh"
 
 
 namespace Rivet {
 
   using RivetHepMC::GenEvent;
   using ConstGenEventPtr = std::shared_ptr<const GenEvent>;
   /// @todo Use mcutils?
 
   namespace HepMCUtils{
 
     ConstGenParticlePtr              getParticlePtr(const RivetHepMC::GenParticle & gp);
     std::vector<ConstGenParticlePtr> particles(ConstGenEventPtr ge);
     std::vector<ConstGenParticlePtr> particles(const GenEvent *ge);
     std::vector<ConstGenVertexPtr>   vertices(ConstGenEventPtr ge);
     std::vector<ConstGenVertexPtr>   vertices(const GenEvent *ge);
     std::vector<ConstGenParticlePtr> particles(ConstGenVertexPtr gv, const Relatives &relo);
     std::vector<ConstGenParticlePtr> particles(ConstGenParticlePtr gp, const Relatives &relo);
     int uniqueId(ConstGenParticlePtr gp);
     int particles_size(ConstGenEventPtr ge);
     int particles_size(const GenEvent *ge);
     std::pair<ConstGenParticlePtr,ConstGenParticlePtr> beams(const GenEvent *ge);
     std::shared_ptr<HepMC_IO_type> makeReader(std::istream &istr,
                                               std::string * errm = 0);
     bool readEvent(std::shared_ptr<HepMC_IO_type> io,
                    std::shared_ptr<GenEvent> evt);
     void strip(GenEvent & ge,
                const set<long> & stripid = {1, -1, 2, -2, 3,-3, 21});
   }
-
-  inline GenVertexIterRange particles_out(GenVertex* gv) {
-    return GenVertexIterRange(gv->particles_out_begin(), gv->particles_out_end());
-  }
-
-  #endif
-
-
-  //////////////////////////
-
-
-  /// Get the direct parents or all-ancestors of GenParticle @a gp
-  inline std::vector<const GenParticle*> particles_in(const GenParticle* gp, HepMC::IteratorRange range=HepMC::ancestors) {
-    if (range != HepMC::parents && range != HepMC::ancestors)
-      throw UserError("Requested particles_in(GenParticle*) with a non-'in' iterator range");
-    if (!gp->production_vertex()) return std::vector<const GenParticle*>();
-    #if HEPMC_VERSION_CODE >= 2007000
-    return particles(gp->production_vertex(), range);
-    #else
-    // Before HepMC 2.7.0 the constness consistency of methods and their return types was all screwed up :-/
-    std::vector<const GenParticle*> rtn;
-    foreach (GenParticle* gp2, particles(gp->production_vertex(), range))
-      rtn.push_back( const_cast<const GenParticle*>(gp2) );
-    return rtn;
-    #endif
-  }
-
-  /// Get the direct parents or all-ancestors of GenParticle @a gp
-  inline std::vector<GenParticle*> particles_in(GenParticle* gp, HepMC::IteratorRange range=HepMC::ancestors) {
-    if (range != HepMC::parents && range != HepMC::ancestors)
-      throw UserError("Requested particles_in(GenParticle*) with a non-'in' iterator range");
-    return (gp->production_vertex()) ? particles(gp->production_vertex(), range) : std::vector<GenParticle*>();
-  }
-
-
-  /// Get the direct children or all-descendents of GenParticle @a gp
-  inline std::vector<const GenParticle*> particles_out(const GenParticle* gp, HepMC::IteratorRange range=HepMC::descendants) {
-    if (range != HepMC::children && range != HepMC::descendants)
-      throw UserError("Requested particles_out(GenParticle*) with a non-'out' iterator range");
-    if (!gp->end_vertex()) return std::vector<const GenParticle*>();
-    #if HEPMC_VERSION_CODE >= 2007000
-    return particles(gp->end_vertex(), range);
-    #else
-    // Before HepMC 2.7.0 the constness consistency of methods and their return types was all screwed up :-/
-    std::vector<const GenParticle*> rtn;
-    foreach (GenParticle* gp2, particles(gp->end_vertex(), range))
-      rtn.push_back( const_cast<const GenParticle*>(gp2) );
-    return rtn;
-    #endif
-  }
-
-  /// Get the direct children or all-descendents of GenParticle @a gp
-  inline std::vector<GenParticle*> particles_out(GenParticle* gp, HepMC::IteratorRange range=HepMC::descendants) {
-    if (range != HepMC::children && range != HepMC::descendants)
-      throw UserError("Requested particles_out(GenParticle*) with a non-'out' iterator range");
-    return (gp->end_vertex()) ? particles(gp->end_vertex(), range) : std::vector<GenParticle*>();
-  }
-
-
-  /// Get any relatives of GenParticle @a gp
-  inline std::vector<const GenParticle*> particles(const GenParticle* gp, HepMC::IteratorRange range=HepMC::ancestors) {
-    if (range == HepMC::parents || range == HepMC::ancestors)
-      return particles_in(gp, range);
-    if (range == HepMC::children || range == HepMC::descendants)
-      return particles_in(gp, range);
-    throw UserError("Requested particles(GenParticle*) with an unsupported iterator range");
-  }
-
-
 }
 
 #endif
diff --git a/src/Core/AnalysisHandler.cc b/src/Core/AnalysisHandler.cc
--- a/src/Core/AnalysisHandler.cc
+++ b/src/Core/AnalysisHandler.cc
@@ -1,716 +1,752 @@
 // -*- C++ -*-
 #include "Rivet/Config/RivetCommon.hh"
 #include "Rivet/AnalysisHandler.hh"
 #include "Rivet/Analysis.hh"
 #include "Rivet/Tools/ParticleName.hh"
 #include "Rivet/Tools/BeamConstraint.hh"
 #include "Rivet/Tools/Logging.hh"
 #include "Rivet/Projections/Beam.hh"
 #include "YODA/IO.h"
 #include <regex>
 #include <iostream>
 
 using std::cout;
 using std::cerr;
 
 namespace {
 
   inline std::vector<std::string> split(const std::string& input, const std::string& regex) {
     // passing -1 as the submatch index parameter performs splitting
     std::regex re(regex);
     std::sregex_token_iterator
       first{input.begin(), input.end(), re, -1},
       last;
       return {first, last};
   }
 
 }
 
 
 namespace Rivet {
 
 
   AnalysisHandler::AnalysisHandler(const string& runname)
     : _runname(runname),
-      _eventcounter("/_EVTCOUNT"),
-      _xs(NAN), _xserr(NAN),
-      _initialised(false), _ignoreBeams(false), _dumpPeriod(0), _dumping(false),
-      _defaultWeightIdx(0)
+      // *** LEIF *** temporarily removed this
+      // _eventcounter("/_EVTCOUNT"),
+      // _xs(NAN), _xserr(NAN),
+      _initialised(false), _ignoreBeams(false),
+      _defaultWeightIdx(0), _dumpPeriod(0), _dumping(false)
   {  }
 
 
   AnalysisHandler::~AnalysisHandler()
   {  }
 
 
   Log& AnalysisHandler::getLog() const {
     return Log::getLog("Rivet.Analysis.Handler");
   }
 
 
   /// http://stackoverflow.com/questions/4654636/how-to-determine-if-a-string-is-a-number-with-c
   namespace {
     bool is_number(const std::string& s) {
       std::string::const_iterator it = s.begin();
       while (it != s.end() && std::isdigit(*it)) ++it;
       return !s.empty() && it == s.end();
     }
   }
 
   /// Check if any of the weightnames is not a number
   bool AnalysisHandler::haveNamedWeights() const {
     bool dec=false;
     for (unsigned int i=0;i<_weightNames.size();++i) {
       string s = _weightNames[i];
       if (!is_number(s)) {
         dec=true;
         break;
       }
     }
     return dec;
   }
 
 
   void AnalysisHandler::init(const GenEvent& ge) {
     if (_initialised)
       throw UserError("AnalysisHandler::init has already been called: cannot re-initialize!");
 
     /// @todo Should the Rivet analysis objects know about weight names?
 
     setRunBeams(Rivet::beams(ge));
     MSG_DEBUG("Initialising the analysis handler");
     _eventNumber = ge.event_number();
 
     setWeightNames(ge);
     if (haveNamedWeights())
         MSG_INFO("Using named weights");
     else
         MSG_INFO("NOT using named weights. Using first weight as nominal weight");
 
     _eventCounter = CounterPtr(weightNames(), Counter("_EVTCOUNT"));
 
     // Set the cross section based on what is reported by this event.
     if (ge.cross_section()) {
       MSG_TRACE("Getting cross section.");
       double xs = ge.cross_section()->cross_section();
       double xserr = ge.cross_section()->cross_section_error();
       setCrossSection(xs, xserr);
     }
 
     // Check that analyses are beam-compatible, and remove those that aren't
     const size_t num_anas_requested = analysisNames().size();
     vector<string> anamestodelete;
     for (const AnaHandle a : analyses()) {
       if (!_ignoreBeams && !a->isCompatible(beams())) {
         //MSG_DEBUG(a->name() << " requires beams " << a->requiredBeams() << " @ " << a->requiredEnergies() << " GeV");
         anamestodelete.push_back(a->name());
       }
     }
     for (const string& aname : anamestodelete) {
       MSG_WARNING("Analysis '" << aname << "' is incompatible with the provided beams: removing");
       removeAnalysis(aname);
     }
     if (num_anas_requested > 0 && analysisNames().empty()) {
       cerr << "All analyses were incompatible with the first event's beams\n"
            << "Exiting, since this probably wasn't intentional!" << endl;
       exit(1);
     }
 
     // Warn if any analysis' status is not unblemished
     for (const AnaHandle a : analyses()) {
       if ( a->info().preliminary() ) {
         MSG_WARNING("Analysis '" << a->name() << "' is preliminary: be careful, it may change and/or be renamed!");
       } else if ( a->info().obsolete() ) {
         MSG_WARNING("Analysis '" << a->name() << "' is obsolete: please update!");
       } else if (( a->info().unvalidated() ) ) {
         MSG_WARNING("Analysis '" << a->name() << "' is unvalidated: be careful, it may be broken!");
       }
     }
 
     // Initialize the remaining analyses
     _stage = Stage::INIT;
     for (AnaHandle a : analyses()) {
       MSG_DEBUG("Initialising analysis: " << a->name());
       try {
         // Allow projection registration in the init phase onwards
         a->_allowProjReg = true;
         a->init();
         //MSG_DEBUG("Checking consistency of analysis: " << a->name());
         //a->checkConsistency();
       } catch (const Error& err) {
         cerr << "Error in " << a->name() << "::init method: " << err.what() << endl;
         exit(1);
       }
       MSG_DEBUG("Done initialising analysis: " << a->name());
     }
     _stage = Stage::OTHER;
     _initialised = true;
     MSG_DEBUG("Analysis handler initialised");
   }
 
+// *** LEIF *** Reinstated this.
+  void AnalysisHandler::setWeightNames(const GenEvent& ge) {
+    /// reroute the print output to a std::stringstream and process
+    /// The iteration is done over a map in hepmc2 so this is safe
+    std::ostringstream stream;
+    ge.weights().print(stream);  // Super lame, I know
+    string str =  stream.str();
+
+    std::regex re("(([^()]+))"); // Regex for stuff enclosed by parentheses ()
+    size_t idx = 0;
+    for (std::sregex_iterator i = std::sregex_iterator(str.begin(), str.end(), re); i != std::sregex_iterator(); ++i ) {
+      std::smatch m = *i;
+      vector<string> temp = ::split(m.str(), "[,]");
+      if (temp.size() ==2) {
+        MSG_DEBUG("Name of weight #" << _weightNames.size() << ": " << temp[0]);
+
+        // store the default weight based on weight names
+        if (temp[0] == "Weight" || temp[0] == "0" || temp[0] == "Default") {
+          MSG_DEBUG(_weightNames.size() << " is being used as the nominal.");
+          _weightNames.push_back("");
+          _defaultWeightIdx = idx;
+        } else
+          _weightNames.push_back(temp[0]);
+
+
+        idx++;
+      }
+    }
+  }
+
+
 
   void AnalysisHandler::analyze(const GenEvent& ge) {
     // Call init with event as template if not already initialised
     if (!_initialised) init(ge);
     assert(_initialised);
 
     // Ensure that beam details match those from the first event (if we're checking beams)
     if ( !_ignoreBeams ) {
       const PdgIdPair beams = Rivet::beamIds(ge);
       const double sqrts = Rivet::sqrtS(ge);
       if (!compatible(beams, _beams) || !fuzzyEquals(sqrts, sqrtS())) {
         cerr << "Event beams mismatch: "
              << PID::toBeamsString(beams) << " @ " << sqrts/GeV << " GeV" << " vs. first beams "
              << this->beams() << " @ " << this->sqrtS()/GeV << " GeV" << endl;
         exit(1);
       }
     }
 
     // Create the Rivet event wrapper
     /// @todo Filter/normalize the event here
     bool strip = ( getEnvParam("RIVET_STRIP_HEPMC", string("NOOOO") ) != "NOOOO" );
     Event event(ge, strip);
 
     // Weights
     /// @todo Drop this / just report first weight when we support multiweight events
-    _eventcounter.fill(event.weight());
-    MSG_DEBUG("Event #" << _eventcounter.numEntries() << " weight = " << event.weight());
+    // *** LEIF *** temporarily removed this
+    // _eventcounter.fill(event.weight());
+    // MSG_DEBUG("Event #" << _eventcounter.numEntries() << " weight = " << event.weight());
 
-    // Cross-section
-    #if defined ENABLE_HEPMC_3
-    if (ge.cross_section()) {
-      //@todo HepMC3::GenCrossSection methods aren't const accessible :(
-      RivetHepMC::GenCrossSection gcs = *(event.genEvent()->cross_section());
-      _xs = gcs.xsec();
-      _xserr = gcs.xsec_err();
-    }
-    #elif defined HEPMC_HAS_CROSS_SECTION
-    if (ge.cross_section()) {
-      _xs = ge.cross_section()->cross_section();
-      _xserr = ge.cross_section()->cross_section_error();
-    }
-    #endif
+    // *** LEIF *** temporarily removed this
+    // // Cross-section
+    // #if defined ENABLE_HEPMC_3
+    // if (ge.cross_section()) {
+    //   //@todo HepMC3::GenCrossSection methods aren't const accessible :(
+    //   RivetHepMC::GenCrossSection gcs = *(event.genEvent()->cross_section());
+    //   _xs = gcs.xsec();
+    //   _xserr = gcs.xsec_err();
+    // }
+    // #elif defined HEPMC_HAS_CROSS_SECTION
+    // if (ge.cross_section()) {
+    //   _xs = ge.cross_section()->cross_section();
+    //   _xserr = ge.cross_section()->cross_section_error();
+    // }
+    // #endif
 
     // Won't happen for first event because _eventNumber is set in init()
     if (_eventNumber != ge.event_number()) {
         /// @todo Can we get away with not passing a matrix?
 
         MSG_TRACE("AnalysisHandler::analyze(): Pushing _eventCounter to persistent.");
         _eventCounter.get()->pushToPersistent(_subEventWeights);
         // if this is indeed a new event, push the temporary
         // histograms and reset
-        for (const AnaHandle& a : _analyses) {
+        for (const AnaHandle& a : analyses()) {
             for (auto ao : a->analysisObjects()) {
                 MSG_TRACE("AnalysisHandler::analyze(): Pushing " << a->name() << "'s " << ao->name() << " to persistent.");
                 ao.get()->pushToPersistent(_subEventWeights);
             }
             MSG_TRACE("AnalysisHandler::analyze(): finished pushing " << a->name() << "'s objects to persistent.");
         }
 
         _eventNumber = ge.event_number();
 
         MSG_DEBUG("nominal event # " << _eventCounter.get()->_persistent[0]->numEntries());
         MSG_DEBUG("nominal sum of weights: " << _eventCounter.get()->_persistent[0]->sumW());
         MSG_DEBUG("Event has " << _subEventWeights.size() << " sub events.");
         _subEventWeights.clear();
     }
 
 
     MSG_TRACE("starting new sub event");
     _eventCounter.get()->newSubEvent();
 
-    for (const AnaHandle& a : _analyses) {
+    for (const AnaHandle& a : analyses()) {
         for (auto ao : a->analysisObjects()) {
             ao.get()->newSubEvent();
         }
     }
 
     _subEventWeights.push_back(event.weights());
     MSG_DEBUG("Analyzing subevent #" << _subEventWeights.size() - 1 << ".");
 
     _eventCounter->fill();
     // Run the analyses
     for (AnaHandle a : analyses()) {
       MSG_TRACE("About to run analysis " << a->name());
       try {
         a->analyze(event);
       } catch (const Error& err) {
         cerr << "Error in " << a->name() << "::analyze method: " << err.what() << endl;
         exit(1);
       }
       MSG_TRACE("Finished running analysis " << a->name());
     }
 
     if ( _dumpPeriod > 0 && numEvents()%_dumpPeriod == 0 ) {
       MSG_INFO("Dumping intermediate results to " << _dumpFile << ".");
       _dumping = numEvents()/_dumpPeriod;
       finalize();
       writeData(_dumpFile);
       _dumping = 0;
     }
 
   }
 
 
   void AnalysisHandler::analyze(const GenEvent* ge) {
     if (ge == nullptr) {
       MSG_ERROR("AnalysisHandler received null pointer to GenEvent");
       //throw Error("AnalysisHandler received null pointer to GenEvent");
     }
     analyze(*ge);
   }
 
 
   void AnalysisHandler::finalize() {
     if (!_initialised) return;
     MSG_INFO("Finalising analyses");
 
     // First push all analyses' objects to persistent
     MSG_TRACE("AnalysisHandler::finalize(): Pushing analysis objects to persistent.");
     _eventCounter.get()->pushToPersistent(_subEventWeights);
-    for (const AnaHandle& a : _analyses) {
+    for (const AnaHandle& a : analyses()) {
       for (auto ao : a->analysisObjects())
         ao.get()->pushToPersistent(_subEventWeights);
     }
 
     // First we make copies of all analysis objects.
-    map<string,AnalysisObjectPtr> backupAOs;
+    map<string,YODA::AnalysisObjectPtr> backupAOs;
     for (auto ao : getData(false, true, false) )
-      backupAOs[ao->path()] = AnalysisObjectPtr(ao->newclone());
+      backupAOs[ao->path()] = YODA::AnalysisObjectPtr(ao->newclone());
 
     // Now we run the (re-entrant) finalize() functions for all analyses.
     MSG_INFO("Finalising analyses");
     for (AnaHandle a : analyses()) {
-      a->setCrossSection(_xs);
+    // *** LEIF *** temporarily removed this
+      // a->setCrossSection(_xs);
       try {
         if ( !_dumping || a->info().reentrant() )  a->finalize();
         else if ( _dumping == 1 )
           MSG_INFO("Skipping finalize in periodic dump of " << a->name()
                    << " as it is not declared reentrant.");
       } catch (const Error& err) {
         cerr << "Error in " << a->name() << "::finalize method: " << err.what() << endl;
         exit(1);
       }
     }
 
     // Now we copy all analysis objects to the list of finalized
     // ones, and restore the value to their original ones.
     _finalizedAOs.clear();
     for ( auto ao : getYodaAOs(false, false, false) )
       _finalizedAOs.push_back(YODA::AnalysisObjectPtr(ao->newclone()));
     for ( auto ao : getYodaAOs(false, true, false) ) {
       // TODO: This should be possible to do in a nicer way, with a flag etc.
       if (ao->path().find("/FINAL") != std::string::npos) continue;
       auto aoit = backupAOs.find(ao->path());
       if ( aoit == backupAOs.end() ) {
         AnaHandle ana = analysis(split(ao->path(), "/")[0]);
         if ( ana ) ana->removeAnalysisObject(ao->path());
       } else
         copyao(aoit->second, ao);
     }
 
     // Print out number of events processed
     const int nevts = numEvents();
     MSG_INFO("Processed " << nevts << " event" << (nevts != 1 ? "s" : ""));
 
     // // Delete analyses
     // MSG_DEBUG("Deleting analyses");
     // _analyses.clear();
 
     // Print out MCnet boilerplate
     cout << endl;
     cout << "The MCnet usage guidelines apply to Rivet: see http://www.montecarlonet.org/GUIDELINES" << endl;
     cout << "Please acknowledge plots made with Rivet analyses, and cite arXiv:1003.0694 (http://arxiv.org/abs/1003.0694)" << endl;
   }
 
 
   AnalysisHandler& AnalysisHandler::addAnalysis(const string& analysisname, std::map<string, string> pars) {
      // Make an option handle.
     std::string parHandle = "";
     for (map<string, string>::iterator par = pars.begin(); par != pars.end(); ++par) {
       parHandle +=":";
       parHandle += par->first + "=" + par->second;
     }
     return addAnalysis(analysisname + parHandle);
   }
 
 
   AnalysisHandler& AnalysisHandler::addAnalysis(const string& analysisname) {
     // Check for a duplicate analysis
     /// @todo Might we want to be able to run an analysis twice, with different params?
     ///       Requires avoiding histo tree clashes, i.e. storing the histos on the analysis objects.
     string ananame = analysisname;
     vector<string> anaopt = split(analysisname, ":");
     if ( anaopt.size() > 1 ) ananame = anaopt[0];
     AnaHandle analysis( AnalysisLoader::getAnalysis(ananame) );
     if (analysis.get() != 0) { // < Check for null analysis.
       MSG_DEBUG("Adding analysis '" << analysisname << "'");
       map<string,string> opts;
       for ( int i = 1, N = anaopt.size(); i < N; ++i ) {
         vector<string> opt = split(anaopt[i], "=");
         if ( opt.size() != 2 ) {
           MSG_WARNING("Error in option specification. Skipping analysis " << analysisname);
           return *this;
         }
         if ( !analysis->info().validOption(opt[0], opt[1]) ) {
           MSG_WARNING("Cannot set option '" << opt[0] << "' to '" << opt[1]
                       << "'. Skipping analysis " << analysisname);
           return *this;
         }
         opts[opt[0]] = opt[1];
       }
       for ( auto opt: opts) {
         analysis->_options[opt.first] = opt.second;
         analysis->_optstring += ":" + opt.first + "=" + opt.second;
       }
       for (const AnaHandle& a : analyses()) {
         if (a->name() == analysis->name() ) {
           MSG_WARNING("Analysis '" << analysisname << "' already registered: skipping duplicate");
           return *this;
         }
       }
       analysis->_analysishandler = this;
       _analyses[analysisname] = analysis;
     } else {
       MSG_WARNING("Analysis '" << analysisname << "' not found.");
     }
     // MSG_WARNING(_analyses.size());
     // for (const AnaHandle& a : _analyses) MSG_WARNING(a->name());
     return *this;
   }
 
 
   AnalysisHandler& AnalysisHandler::removeAnalysis(const string& analysisname) {
     MSG_DEBUG("Removing analysis '" << analysisname << "'");
     if (_analyses.find(analysisname) != _analyses.end()) _analyses.erase(analysisname);
     // }
     return *this;
   }
 
 
   void AnalysisHandler::addData(const std::vector<YODA::AnalysisObjectPtr>& aos) {
     for (const YODA::AnalysisObjectPtr ao : aos) {
       string path = ao->path();
       if ( path.substr(0, 5) != "/RAW/" ) {
         _orphanedPreloads.push_back(ao);
         continue;
       }
 
       path = path.substr(4);
       ao->setPath(path);
       if (path.size() > 1) { // path > "/"
         try {
           const string ananame =  ::split(path, "/")[0];
           AnaHandle a = analysis(ananame);
           /// @todo FIXXXXX
           //MultiweightAOPtr mao = ????; /// @todo generate right Multiweight object from ao
           //a->addAnalysisObject(mao); /// @todo Need to statistically merge...
         } catch (const Error& e) {
           MSG_TRACE("Adding analysis object " << path <<
                     " to the list of orphans.");
           _orphanedPreloads.push_back(ao);
         }
       }
     }
   }
 
 
   void AnalysisHandler::stripOptions(YODA::AnalysisObjectPtr ao,
                                      const vector<string> & delopts) const {
     string path = ao->path();
     string ananame = split(path, "/")[0];
     vector<string> anaopts = split(ananame, ":");
     for ( int i = 1, N = anaopts.size(); i < N; ++i )
       for ( auto opt : delopts )
         if ( opt == "*" || anaopts[i].find(opt + "=") == 0 )
           path.replace(path.find(":" + anaopts[i]), (":" + anaopts[i]).length(), "");
     ao->setPath(path);
   }
 
 
   void AnalysisHandler::mergeYodas(const vector<string> & ,
                                    const vector<string> & , bool ) {}
   // void AnalysisHandler::mergeYodas(const vector<string> & aofiles,
   //                                  const vector<string> & delopts, bool equiv) {
   //   vector< vector<YODA::AnalysisObjectPtr> > aosv;
   //   vector<double> xsecs;
   //   vector<double> xsecerrs;
   //   vector<CounterPtr> sows;
   //   set<string> ananames;
   //   _eventCounter->reset();
 
   //   // First scan all files and extract analysis objects and add the
   //   // corresponding analyses..
   //   for (const string& file : aofiles ) {
   //     Scatter1DPtr xsec;
   //     CounterPtr sow;
 
   //     // For each file make sure that cross section and sum-of-weights
   //     // objects are present and stor all RAW ones in a vector;
   //     vector<YODA::AnalysisObjectPtr> aos;
   //     try {
   //       /// @todo Use new YODA SFINAE to fill the smart ptr vector directly
   //       vector<YODA::AnalysisObject*> aos_raw;
   //       YODA::read(file, aos_raw);
   //       for (YODA::AnalysisObject* aor : aos_raw) {
   //         YODA::AnalysisObjectPtr ao(aor);
   //         if ( ao->path().substr(0, 5) != "/RAW/" ) continue;
   //         ao->setPath(ao->path().substr(4));
   //         if ( ao->path() == "/_XSEC" )
   //           xsec = dynamic_pointer_cast<Scatter1D>(ao);
   //         else if ( ao->path() == "/_EVTCOUNT" )
   //           sow = dynamic_pointer_cast<Counter>(ao);
   //         else {
   //           stripOptions(ao, delopts);
   //           string ananame = split(ao->path(), "/")[0];
   //           if ( ananames.insert(ananame).second ) addAnalysis(ananame);
   //           aos.push_back(ao);
   //         }
   //       }
   //       if ( !xsec || !sow ) {
   //         MSG_ERROR( "Error in AnalysisHandler::mergeYodas: The file " << file
   //                    << " did not contain weights and cross section info.");
   //         exit(1);
   //       }
   //       xsecs.push_back(xsec->point(0).x());
   //       sows.push_back(sow);
   //       xsecerrs.push_back(sqr(xsec->point(0).xErrAvg()));
   //       _eventCounter->operator+=(*sow); //< HAHAHAHAHA!
   //       sows.push_back(sow);
   //       aosv.push_back(aos);
   //     } catch (...) { //< YODA::ReadError&
   //       throw UserError("Unexpected error in reading file: " + file);
   //     }
   //   }
 
   //   // Now calculate the scale to be applied for all bins in a file
   //   // and get the common cross section and sum of weights.
   //   _xs = _xserr = 0.0;
   //   for ( int i = 0, N = sows.size(); i < N; ++i ) {
   //     double effnent = sows[i]->effNumEntries();
   //     _xs += (equiv? effnent: 1.0)*xsecs[i];
   //     _xserr += (equiv? sqr(effnent): 1.0)*xsecerrs[i];
   //   }
 
   //   vector<double> scales(sows.size(), 1.0);
   //   if ( equiv ) {
   //     _xs /= _eventCounter.effNumEntries();
   //     _xserr = sqrt(_xserr)/_eventCounter.effNumEntries();
   //   } else {
   //     _xserr = sqrt(_xserr);
   //     for ( int i = 0, N = sows.size(); i < N; ++i )
   //       scales[i] = (_eventCounter.sumW()/sows[i]->sumW())*(xsecs[i]/_xs);
   //   }
 
   //   // Initialize the analyses allowing them to book analysis objects.
   //   for (AnaHandle a : _analyses) {
   //     MSG_DEBUG("Initialising analysis: " << a->name());
   //     if ( !a->info().reentrant() )
   //       MSG_WARNING("Analysis " << a->name() << " has not been validated to have "
   //                   << "a reentrant finalize method. The result is unpredictable.");
   //     try {
   //       // Allow projection registration in the init phase onwards
   //       a->_allowProjReg = true;
   //       cerr << "sqrtS " << sqrtS() << endl;
   //       a->init();
   //       //MSG_DEBUG("Checking consistency of analysis: " << a->name());
   //       //a->checkConsistency();
   //     } catch (const Error& err) {
   //       cerr << "Error in " << a->name() << "::init method: " << err.what() << endl;
   //       exit(1);
   //     }
   //     MSG_DEBUG("Done initialising analysis: " << a->name());
   //   }
   //   _initialised = true;
   //   // Get a list of all anaysis objects to handle.
   //   map<string,AnalysisObjectPtr> current;
   //   for ( auto ao : getData(false, true) ) current[ao->path()] = ao;
   //   // Go through all objects to be merged and add them to current
   //   // after appropriate scaling.
   //   for ( int i = 0, N = aosv.size(); i < N; ++i)
   //     for ( auto ao : aosv[i] ) {
   //       if ( ao->path() == "/_XSEC" || ao->path() == "_EVTCOUNT" ) continue;
   //       auto aoit = current.find(ao->path());
   //       if ( aoit == current.end() ) {
   //         MSG_WARNING("" << ao->path() << " was not properly booked.");
   //         continue;
   //       }
   //       if ( !addaos(aoit->second, ao, scales[i]) )
   //         MSG_WARNING("Cannot merge objects with path " << ao->path()
   //                     <<" of type " << ao->annotation("Type") );
   //     }
   //   // Now we can simply finalize() the analysis, leaving the
   //   // controlling program to write it out some yoda-file.
   //   finalize();
   // }
 
 
   void AnalysisHandler::readData(const string& filename) {
     vector<YODA::AnalysisObjectPtr> aos;
     try {
       /// @todo Use new YODA SFINAE to fill the smart ptr vector directly
       vector<YODA::AnalysisObject*> aos_raw;
       YODA::read(filename, aos_raw);
       for (YODA::AnalysisObject* aor : aos_raw) aos.push_back(YODA::AnalysisObjectPtr(aor));
     //} catch (const YODA::ReadError & e) {
     } catch (...) { //< YODA::ReadError&
       throw UserError("Unexpected error in reading file: " + filename);
     }
     if (!aos.empty()) addData(aos);
   }
 
 
   vector<MultiweightAOPtr> AnalysisHandler::getRivetAOs() const {
       vector<MultiweightAOPtr> rtn;
 
-      for (AnaHandle a : _analyses) {
+      for (AnaHandle a : analyses()) {
           for (const auto & ao : a->analysisObjects()) {
               rtn.push_back(ao);
           }
       }
 
       rtn.push_back(_eventCounter);
       rtn.push_back(_xs);
 
       return rtn;
   }
 
   vector<YODA::AnalysisObjectPtr> AnalysisHandler::getYodaAOs(bool includeorphans,
                                                               bool includetmps,
                                                               bool usefinalized) const {
       vector<YODA::AnalysisObjectPtr> rtn;
       if (usefinalized)
         rtn = _finalizedAOs;
       else {
         for (auto rao : getRivetAOs()) {
           // need to set the index
           // before we can search the PATH
           rao.get()->setActiveWeightIdx(_defaultWeightIdx);
           // Exclude paths from final write-out if they contain a "TMP" layer (i.e. matching "/TMP/")
           if (!includetmps && rao->path().find("/TMP/") != string::npos)
             continue;
 
           for (size_t iW = 0; iW < numWeights(); iW++) {
             rao.get()->setActiveWeightIdx(iW);
             rtn.push_back(rao.get()->activeYODAPtr());
           }
         }
       }
 
       // Sort histograms alphanumerically by path before write-out
       sort(rtn.begin(), rtn.end(),
            [](YODA::AnalysisObjectPtr a, YODA::AnalysisObjectPtr b) {
                 return a->path() < b->path();
             }
           );
 
       return rtn;
   }
 
 
   vector<YODA::AnalysisObjectPtr> AnalysisHandler::getData(bool includeorphans,
                                                            bool includetmps,
                                                            bool usefinalized) const {
     return getYodaAOs(includeorphans, includetmps, usefinalized);
   }
 
 
   void AnalysisHandler::writeData(const string& filename) const {
     vector<YODA::AnalysisObjectPtr> out = _finalizedAOs;
     set<string> finalana;
     for ( auto ao : out) finalana.insert(ao->path());
     out.reserve(2*out.size());
-    vector<AnalysisObjectPtr> aos = getData(false, true);
+    vector<YODA::AnalysisObjectPtr> aos = getData(false, true);
     for ( auto ao : aos ) {
       ao = YODA::AnalysisObjectPtr(ao->newclone());
       ao->setPath("/RAW" + ao->path());
       out.push_back(ao);
     }
 
     try {
       YODA::write(filename, aos.begin(), aos.end());
     } catch (...) { //< YODA::WriteError&
       throw UserError("Unexpected error in writing file: " + filename);
     }
   }
 
 
   string AnalysisHandler::runName() const { return _runname; }
   size_t AnalysisHandler::numEvents() const { return _eventCounter->numEntries(); }
 
 
   std::vector<std::string> AnalysisHandler::analysisNames() const {
     std::vector<std::string> rtn;
     for (AnaHandle a : analyses()) {
       rtn.push_back(a->name());
     }
     return rtn;
   }
 
 
   AnalysisHandler& AnalysisHandler::addAnalyses(const std::vector<std::string>& analysisnames) {
     for (const string& aname : analysisnames) {
       //MSG_DEBUG("Adding analysis '" << aname << "'");
       addAnalysis(aname);
     }
     return *this;
   }
 
 
   AnalysisHandler& AnalysisHandler::removeAnalyses(const std::vector<std::string>& analysisnames) {
     for (const string& aname : analysisnames) {
       removeAnalysis(aname);
     }
     return *this;
   }
 
 
   AnalysisHandler& AnalysisHandler::setCrossSection(double xs, double xserr) {
     _xs = Scatter1DPtr(weightNames(), Scatter1D("_XSEC"));
     _eventCounter.get()->setActiveWeightIdx(_defaultWeightIdx);
     double nomwgt = sumW();
 
     // The cross section of each weight variation is the nominal cross section
     // times the sumW(variation) / sumW(nominal).
     // This way the cross section will work correctly
     for (size_t iW = 0; iW < numWeights(); iW++) {
       _eventCounter.get()->setActiveWeightIdx(iW);
       double s = sumW() / nomwgt;
       _xs.get()->setActiveWeightIdx(iW);
       _xs->addPoint(xs*s, xserr*s);
     }
 
     _eventCounter.get()->unsetActiveWeight();
     _xs.get()->unsetActiveWeight();
     return *this;
   }
 
 
-  bool AnalysisHandler::hasCrossSection() const {
-    return (!std::isnan(crossSection()));
-  }
+  // *** LEIF *** temporarily removed this
+  // bool AnalysisHandler::hasCrossSection() const {
+  //   return (!std::isnan(crossSection()));
+  // }
 
 
   AnalysisHandler& AnalysisHandler::addAnalysis(Analysis* analysis) {
     analysis->_analysishandler = this;
     // _analyses.insert(AnaHandle(analysis));
     _analyses[analysis->name()] = AnaHandle(analysis);
     return *this;
   }
 
 
   PdgIdPair AnalysisHandler::beamIds() const {
     return Rivet::beamIds(beams());
   }
 
 
   double AnalysisHandler::sqrtS() const {
     return Rivet::sqrtS(beams());
   }
 
   void AnalysisHandler::setIgnoreBeams(bool ignore) {
     _ignoreBeams=ignore;
   }
 
 
 }
diff --git a/src/Core/ProjectionHandler.cc b/src/Core/ProjectionHandler.cc
--- a/src/Core/ProjectionHandler.cc
+++ b/src/Core/ProjectionHandler.cc
@@ -1,261 +1,262 @@
 // -*- C++ -*-
 #include "Rivet/Config/RivetCommon.hh"
 #include "Rivet/ProjectionHandler.hh"
 #include "Rivet/Tools/Cmp.hh"
 #include <algorithm>
 #include <iostream>
 
 using std::cerr;
+using std::endl;
 
 namespace {
   // Get a logger.
   Rivet::Log& getLog() {
     return Rivet::Log::getLog("Rivet.ProjectionHandler");
   }
 }
 
 namespace Rivet {
 
 
   // Take a Projection, compare it to the others on record, and return (by
   // reference) an equivalent Projection which is guaranteed to be the
   // (persistent) version that will be applied to an event.
   const Projection& ProjectionHandler::registerProjection(const ProjectionApplier& parent,
                                                           const Projection& proj,
                                                           const string& name)
   {
     getLog() << Log::TRACE << "Trying to register"
              << " projection " << &proj  << " (" << proj.name() << ")"
              << " for parent " << &parent << " (" << parent.name() << ")"
              << " with name '" << name << "'" << endl;
 
     // Check for duplicate use of "name" on "parent"
     const bool dupOk = _checkDuplicate(parent, proj, name);
     if (!dupOk) {
       cerr << "Duplicate name '" << name << "' in parent '" << parent.name() << "'." << endl;
       exit(1);
     }
 
     // Choose which version of the projection to register with this parent and name
     ProjHandle ph = _getEquiv(proj);
     if ( ph ) {
       const Projection & ret = _register(parent, ph, name);
       return ret;
     } else {
       unique_ptr<Projection> p = _clone(proj);
       const Projection & ret = _register(parent, move(p), name);
       // Return registered proj
       return ret;
     }
   }
 
   // Clone neatly
   unique_ptr<Projection> ProjectionHandler::_clone(const Projection& proj)
   {
     // Clone a new copy of the passed projection on the heap
     getLog() << Log::TRACE << "Cloning projection " << proj.name() << " from " << &proj << "..." << endl;
     unique_ptr<Projection> newproj = proj.clone();
     getLog() << Log::TRACE << "...cloned to " << proj.name() << " at " << newproj.get() << endl;
 
     // Copy all the child ProjHandles when cloning, since otherwise links to "stack parents"
     // will be generated by their children, without any connection to the cloned parent
     if (&proj != newproj.get()) {
       auto nps = _namedprojs.find(&proj);
       if (nps != _namedprojs.end()) {
         getLog() << Log::TRACE << "Cloning registered projections list: "
                  << &proj << " -> " << newproj.get() << endl;
         getLog() << Log::TRACE  << "** creates " << newproj.get() << " -> (map from " << nps->first << ")\n";
         _namedprojs[newproj.get()] = nps->second;
       }
     }
 
     return newproj;
   }
 
 
 
   // Take a Projection, and register it in the registry.
   const Projection& ProjectionHandler::_register(const ProjectionApplier& parent,
                                                  ProjHandle p,
                                                  const string& name)
   {
     // here we take ownership of the projection
     getLog() << Log::TRACE << "Registering new projection at " << p.get()
       << ". Starting refcount: " << p.use_count() << endl;
 
     // Add the passed Projection to _projs
 
     _projs.insert(p);
     getLog() << Log::TRACE
       << "** inserted " << p.get() << " to lookup. Refcount: " << p.use_count() << endl;
 
 
     // Add the ProjApplier* => name location to the associative container
     _namedprojs[&parent][name] = p;
     getLog() << Log::TRACE
       << "** created " << &parent << " -> (" << name << ',' <<
                                             p.get() << "). Refcount: " << p.use_count() << endl;
 
     p->markAsOwned();
 
     return *p;
   }
 
 
 
 
   // Try to find a equivalent projection in the system
   ProjHandle ProjectionHandler::_getEquiv(const Projection& proj) const
   {
     // Get class type using RTTI
     const std::type_info& newtype = typeid(proj);
     getLog() << Log::TRACE << "RTTI type of " << &proj << " is " << newtype.name() << endl;
 
     // Compare to ALL projections via _projs collection
     getLog() << Log::TRACE << "Comparing " << &proj
              << " with " << _projs.size()
              << " registered projection" << (_projs.size() == 1 ? "" : "s") <<  endl;
     for (const ProjHandle& ph : _projs) {
       // Make sure the concrete types match, using RTTI.
       const std::type_info& regtype = typeid(*ph);
       getLog() << Log::TRACE << "  RTTI type comparison with " << ph << ": "
                << newtype.name() << " vs. " << regtype.name() << endl;
       if (newtype != regtype) continue;
       getLog() << Log::TRACE << "  RTTI type matches with " << ph << endl;
 
       // Test for semantic match
       if (pcmp(*ph, proj) != CmpState::EQ) {
         getLog() << Log::TRACE << "  Projections at "
                  << &proj << " and " << ph << " are not equivalent" << endl;
       } else {
         getLog() << Log::TRACE << "  MATCH! Projections at "
                  << &proj << " and " << ph << " are equivalent" << endl;
         return ph;
       }
     }
     getLog() << Log::TRACE << "  Nothing matches." << endl;
     // If no match, just return a null pointer
     return nullptr;
   }
 
 
 
   string ProjectionHandler::_getStatus() const {
-    ostringstream msg;
+    std::ostringstream msg;
     msg << "Current projection hierarchy:" << endl;
     for (const NamedProjsMap::value_type& nps : _namedprojs) {
       //const string parentname = nps.first->name();
       msg << nps.first << endl; //"(" << parentname << ")" << endl;
       for (const NamedProjs::value_type& np : nps.second) {
         msg << "  " << np.second << " (" << np.second->name()
             << ", locally called '" << np.first << "')" << endl;
       }
       msg << endl;
     }
     return msg.str();
   }
 
 
 
   // Check that the same parent hasn't already used this name for something else
   bool ProjectionHandler::_checkDuplicate(const ProjectionApplier& parent,
                                           const Projection& proj,
                                           const string& name) const
   {
     auto listedParent = _namedprojs.find(&parent);
     if (listedParent != _namedprojs.end()) {
       const NamedProjs pnps = listedParent->second;
       const NamedProjs::const_iterator ipph = pnps.find(name);
       if (ipph != pnps.end()) {
         const ProjHandle pph = ipph->second;
         getLog() << Log::ERROR << "Projection clash! "
                  << parent.name() << " (" << &parent << ") "
                  << "is trying to overwrite its registered '" << name << "' "
                  << "projection (" << pph << "="
                  << pph->name() << ") with a non-equivalent projection "
                  << "(" << &proj << "=" << proj.name() << ")" << endl;
         getLog() << Log::ERROR << _getStatus();
         return false;
       }
     }
     return true;
   }
 
 
 
 
   void ProjectionHandler::removeProjectionApplier(ProjectionApplier& parent) {
     auto npi = _namedprojs.find(&parent);
     if (npi != _namedprojs.end()) {
        getLog() << Log::TRACE << "REMOVE Projection at "
                  << &parent << " from map" << endl;
       _namedprojs.erase(npi);
     }
     //
     auto pAsProj = dynamic_cast<Projection*>(&parent);
     if (pAsProj) {
       auto pi = find_if(_projs.begin(), _projs.end(),
                         [pAsProj](ProjHandle h)->bool { return h.get() == pAsProj; } );
       if (pi != _projs.end()) {
           getLog() << Log::TRACE << "REMOVE Projection at "
                    << pAsProj << " from lookup" << endl;
           _projs.erase(pi);
 
       }
     }
   }
 
 
   set<const Projection*> ProjectionHandler::getChildProjections(const ProjectionApplier& parent, ProjDepth depth) const {
     set<const Projection*> toplevel;
     NamedProjs nps = _namedprojs.find(&parent)->second;
     for (NamedProjs::value_type& np : nps) {
       toplevel.insert(np.second.get());
     }
     if (depth == SHALLOW) {
       // Only return the projections directly contained within the top level
       return toplevel;
     } else {
       // Return recursively built projection list
       set<const Projection*> alllevels = toplevel;
       for (const Projection* p : toplevel) {
         set<const Projection*> allsublevels = getChildProjections(*p, DEEP);
         alllevels.insert(allsublevels.begin(), allsublevels.end());
       }
       return alllevels;
     }
   }
 
 
   bool ProjectionHandler::hasProjection(const ProjectionApplier& parent, const string& name) const {
     MSG_TRACE("Searching for child projection '" << name << "' of " << &parent);
     NamedProjsMap::const_iterator nps = _namedprojs.find(&parent);
     if (nps == _namedprojs.end()) return false;
     NamedProjs::const_iterator np = nps->second.find(name);
     return !(np == nps->second.end());
   }
 
 
   const Projection& ProjectionHandler::getProjection(const ProjectionApplier& parent, const string& name) const {
     MSG_TRACE("Searching for child projection '" << name << "' of " << &parent);
     NamedProjsMap::const_iterator nps = _namedprojs.find(&parent);
     if (nps == _namedprojs.end()) {
       std::ostringstream msg;
       msg << "No projections registered for parent " << &parent;
       throw Error(msg.str());
     }
     NamedProjs::const_iterator np = nps->second.find(name);
     if (np == nps->second.end()) {
       std::ostringstream msg;
       msg << "No projection '" << name << "' found for parent " << &parent;
       throw Error(msg.str());
     }
     MSG_TRACE("Found projection '" << name << "' of " << &parent << " -> " << np->second);
     // If it's registered with the projection handler, we must be able to safely
     // dereference the Projection pointer to a reference...
     return *(np->second);
   }
 
 
 
 }
diff --git a/src/Core/Run.cc b/src/Core/Run.cc
--- a/src/Core/Run.cc
+++ b/src/Core/Run.cc
@@ -1,172 +1,176 @@
 // -*- C++ -*-
 #include "Rivet/Run.hh"
 #include "Rivet/AnalysisHandler.hh"
 #include "Rivet/Math/MathUtils.hh"
 #include "Rivet/Tools/RivetPaths.hh"
 #include "zstr/zstr.hpp"
 #include <limits>
 #include <iostream>
 
 using std::cout;
 using std::endl;
 
 namespace Rivet {
 
 
   Run::Run(AnalysisHandler& ah)
     : _ah(ah), _fileweight(1.0), _xs(NAN)
   { }
 
 
   Run::~Run() { }
 
 
   Run& Run::setCrossSection(const double xs) {
     _xs = xs;
     return *this;
   }
 
 
   Run& Run::setListAnalyses(const bool dolist) {
     _listAnalyses = dolist;
     return *this;
   }
 
 
   // Fill event and check for a bad read state
   bool Run::readEvent() {
     /// @todo Clear rather than new the GenEvent object per-event?
     _evt.reset(new GenEvent());
     if(!HepMCUtils::readEvent(_hepmcReader, _evt)){
       Log::getLog("Rivet.Run") << Log::DEBUG << "Read failed. End of file?" << endl;
       return false;
     }
     // Rescale event weights by file-level weight, if scaling is non-trivial
     if (!fuzzyEquals(_fileweight, 1.0)) {
       for (size_t i = 0; i < (size_t) _evt->weights().size(); ++i) {
         _evt->weights()[i] *= _fileweight;
       }
     }
     return true;
   }
 
 
 
   bool Run::openFile(const std::string& evtfile, double weight) {
     // Set current weight-scaling member
     _fileweight = weight;
 
     // In case makeReader fails.
     std::string errormessage;
     
     // Set up HepMC input reader objects
     if (evtfile == "-") {
 #ifdef HAVE_LIBZ
       _istr = make_shared<zstr::istream>(std::cin);
       _hepmcReader = HepMCUtils::makeReader(*_istr, &errormessage);
 #else
       _hepmcReader = HepMCUtils::makeReader(std::cin, &errormessage);
 #endif
     } else {
       if ( !fileexists(evtfile) )
         throw Error("Event file '" + evtfile + "' not found");
 #ifdef HAVE_LIBZ
       // NB. zstr auto-detects if file is deflated or plain-text
       _istr = make_shared<zstr::ifstream>(evtfile.c_str());
 #else
       _istr = make_shared<std::ifstream>(evtfile.c_str());
 #endif
       _hepmcReader = HepMCUtils::makeReader(*_istr, &errormessage);
       
     }
 
     if (_hepmcReader == nullptr) {
       Log::getLog("Rivet.Run")
         << Log::ERROR << "Read error on file '" << evtfile << "' "
         << errormessage << endl;
       return false;
     }
     return true;
   }
 
 
   bool Run::init(const std::string& evtfile, double weight) {
     if (!openFile(evtfile, weight)) return false;
 
     // Read first event to define run conditions
     bool ok = readEvent();
     if (!ok) return false;
     if(HepMCUtils::particles(_evt).size() == 0){
       Log::getLog("Rivet.Run") << Log::ERROR << "Empty first event." << endl;
       return false;
     }
 
     // Initialise AnalysisHandler with beam information from first event
     _ah.init(*_evt);
 
     // Set cross-section from command line
     if (!std::isnan(_xs)) {
       Log::getLog("Rivet.Run")
         << Log::DEBUG << "Setting user cross-section = " << _xs << " pb" << endl;
-      _ah.setCrossSection(_xs);
+      _ah.setCrossSection(_xs, 0.0);
+      // *** LEIF *** check if second argument should be 0.
     }
 
     // List the chosen & compatible analyses if requested
     if (_listAnalyses) {
       for (const std::string& ana : _ah.analysisNames()) {
         cout << ana << endl;
       }
     }
 
     return true;
   }
 
 
   bool Run::processEvent() {
     // Set cross-section if found in event and not from command line
     
     #if defined ENABLE_HEPMC_3
     if (std::isnan(_xs) && _evt->cross_section()) {
       const double xs = _evt->cross_section()->xsec(); ///< in pb
       Log::getLog("Rivet.Run")
       << Log::DEBUG << "Setting cross-section = " << xs << " pb" << endl;
       _ah.setCrossSection(xs);
     }
     #elif defined HEPMC_HAS_CROSS_SECTION
     if (std::isnan(_xs) && _evt->cross_section()) {
       const double xs = _evt->cross_section()->cross_section(); ///< in pb
       Log::getLog("Rivet.Run")
       << Log::DEBUG << "Setting cross-section = " << xs << " pb" << endl;
-      _ah.setCrossSection(xs);
+      _ah.setCrossSection(xs, 0.0);
+      // *** LEIF *** check if second argument should be 0.
     }
     #endif
-    
-    // Complain about absence of cross-section if required!
-    if (_ah.needCrossSection() && !_ah.hasCrossSection()) {
-      Log::getLog("Rivet.Run")
-        << Log::ERROR
-        << "Total cross-section needed for at least one of the analyses. "
-        << "Please set it (on the command line with '-x' if using the 'rivet' program)" << endl;
-      return false;
-    }
+
+    // *** LEIF *** temporarily removed this
+    // // Complain about absence of cross-section if required!
+    // if (_ah.needCrossSection() && !_ah.hasCrossSection()) {
+    //   Log::getLog("Rivet.Run")
+    //     << Log::ERROR
+    //     << "Total cross-section needed for at least one of the analyses. "
+    //     << "Please set it (on the command line with '-x' if using the 'rivet' program)" << endl;
+    //   return false;
+    // }
 
     // Analyze event
     _ah.analyze(*_evt);
 
     return true;
   }
 
 
   bool Run::finalize() {
     _evt.reset();
     /// @todo reinstate for HepMC3
     //_istr.reset();
 
-    if (!std::isnan(_xs)) _ah.setCrossSection(_xs);
+    // *** LEIF *** temporarily removed this
+    // if (!std::isnan(_xs)) _ah.setCrossSection(_xs);
     _ah.finalize();
 
     return true;
   }
 
 
 }
diff --git a/src/Projections/ChargedFinalState.cc b/src/Projections/ChargedFinalState.cc
--- a/src/Projections/ChargedFinalState.cc
+++ b/src/Projections/ChargedFinalState.cc
@@ -1,45 +1,47 @@
 // -*- C++ -*-
 #include "Rivet/Projections/ChargedFinalState.hh"
 
 namespace Rivet {
 
 
   ChargedFinalState::ChargedFinalState(const FinalState& fsp) {
     setName("ChargedFinalState");
     declare(fsp, "FS");
   }
 
   ChargedFinalState::ChargedFinalState(const Cut& c) {
     setName("ChargedFinalState");
     declare(FinalState(c), "FS");
   }
 
   CmpState ChargedFinalState::compare(const Projection& p) const {
     return mkNamedPCmp(p, "FS");
   }
 }
 
 namespace {
   inline bool chargedParticleFilter(const Rivet::Particle& p) {
-    return Rivet::PID::threeCharge(p.pdgId()) == 0;
+    // *** LEIF *** temporarily changed this
+    // return Rivet::PID::threeCharge(p.pdgId()) == 0;
+    return Rivet::PID::charge3(p.pid()) == 0;
   }
 }
 
 namespace Rivet {
   void ChargedFinalState::project(const Event& e) {
     const FinalState& fs = applyProjection<FinalState>(e, "FS");
     // _theParticles.clear();
     // std::remove_copy_if(fs.particles().begin(), fs.particles().end(),
     //                     std::back_inserter(_theParticles),
     //                     [](const Rivet::Particle& p) { return p.charge3() == 0; });
     _theParticles = filter_select(fs.particles(), isCharged);
     MSG_DEBUG("Number of charged final-state particles = " << _theParticles.size());
     if (getLog().isActive(Log::TRACE)) {
       for (const Particle&  p : _theParticles) {
         MSG_TRACE("Selected: " << p.pid() << ", charge = " << p.charge());
       }
     }
   }
 
 
 }
diff --git a/src/Projections/DISDiffHadron.cc b/src/Projections/DISDiffHadron.cc
--- a/src/Projections/DISDiffHadron.cc
+++ b/src/Projections/DISDiffHadron.cc
@@ -1,49 +1,49 @@
 // -*- C++ -*-
 #include "Rivet/Projections/DISDiffHadron.hh"
 
 namespace Rivet {
 
 
-  int DISDiffHadron::compare(const Projection& p) const {
+  CmpState DISDiffHadron::compare(const Projection& p) const {
     return mkNamedPCmp(p, "Beam") || mkNamedPCmp(p, "FS");
   }
 
 
   void DISDiffHadron::project(const Event& e) {
 
       // Find incoming lepton beam
       const ParticlePair& inc = applyProjection<Beam>(e, "Beam").beams();
       bool firstIsHadron = PID::isHadron(inc.first.pid());
       bool secondIsHadron = PID::isHadron(inc.second.pid());
       if (firstIsHadron && !secondIsHadron) {
         _incoming = inc.first;
       } else if (!firstIsHadron && secondIsHadron) {
         _incoming = inc.second;
       } else {
         fail();
         return;
       }
 
       const FinalState & fs = applyProjection<FinalState>(e, "FS");
       Particles fshadrons;
       if ( _incoming.momentum().pz() >= 0.0 )
         fshadrons = fs.particles(isHadron, cmpMomByDescEta);
       else
         fshadrons = fs.particles(isHadron, cmpMomByEta);
 
       Particles sfhadrons = filter_select(fshadrons,
                                           Cuts::pid == _incoming.pid());
       MSG_DEBUG("SF hadrons = " << sfhadrons.size() <<
                 ", all hadrons = " << fshadrons.size());
       if (!sfhadrons.empty()) {
         _outgoing = sfhadrons.front();
       } else if (!fshadrons.empty()) {
         _outgoing = fshadrons.front();
       } else {
         fail();
       }
 
     }
 
 
 }
diff --git a/src/Projections/DISRapidityGap.cc b/src/Projections/DISRapidityGap.cc
--- a/src/Projections/DISRapidityGap.cc
+++ b/src/Projections/DISRapidityGap.cc
@@ -1,154 +1,154 @@
 // -*- C++ -*-
 #include "Rivet/Projections/DISRapidityGap.hh"
 
 namespace Rivet {
 
 
-  int DISRapidityGap::compare(const Projection& p) const {
+  CmpState DISRapidityGap::compare(const Projection& p) const {
     return mkNamedPCmp(p, "DISKIN") || mkNamedPCmp(p, "DISFS");
   }
 
 
   void DISRapidityGap::project(const Event& e) {
     const DISKinematics& dk =
       apply<DISKinematics>(e, "DISKIN");
     const Particles& p =
       apply<DISFinalState>(e, "DISFS").particles(cmpMomByEta);
     findgap(p, dk);
   }
 
   void DISRapidityGap::clearAll() {
     _M2X = _M2Y = _t = _gap = 0.;
     _gapUpp = _gapLow = -8.;
     _ePpzX_HCM = _eMpzX_HCM =_ePpzX_LAB =
       _eMpzX_LAB = _ePpzX_XCM = _eMpzX_XCM = 0.;
     _momX_HCM.setPE(0., 0., 0., 0.);
     _momY_HCM.setPE(0., 0., 0., 0.);
     _momX_XCM.setPE(0., 0., 0., 0.);
     _momY_XCM.setPE(0., 0., 0., 0.);
     _momX_LAB.setPE(0., 0., 0., 0.);
     _momY_LAB.setPE(0., 0., 0., 0.);
     _pX_HCM.clear();
     _pY_HCM.clear();
     _pX_XCM.clear();
     _pY_XCM.clear();
     _pX_LAB.clear();
     _pY_LAB.clear();
   }
 
   void DISRapidityGap::findgap(const Particles& particles,
                                const DISKinematics& diskin) {
 
     clearAll();
 
     // Begin by finding largest gap and gapedges between all final
     // state particles in HCM frame.
     int nP  = particles.size();
     int dir = diskin.orientation();
     for (int i = 0; i < nP-1; ++i){
       double tmpGap = abs(particles[i+1].eta() - particles[i].eta());
       if (tmpGap > _gap) {
         _gap    = tmpGap;
         _gapLow = (dir > 0) ? particles[i].eta() : dir * particles[i+1].eta();
         _gapUpp = (dir > 0) ? particles[i+1].eta() : dir * particles[i].eta();
       }
     }
 
     // Define the two systems X and Y.
     Particles tmp_pX, tmp_pY;
-    foreach (const Particle& ip, particles) {
+    for (const Particle& ip : particles) {
       if (dir * ip.eta() > _gapLow) tmp_pX.push_back(ip);
       else tmp_pY.push_back(ip);
     }
 
     Particles pX, pY;
     pX = (dir < 0) ? tmp_pY : tmp_pX;
     pY = (dir < 0) ? tmp_pX : tmp_pY;
 
     // Find variables related to HCM frame.
     // Note that HCM has photon along +z, as opposed to
     // H1 where proton is along +z. This results in a sign change
     // as compared to H1 papers!
       
     // X - side
     FourMomentum momX;
     for (const Particle& jp : pX) {
       momX  += jp.momentum();
       _ePpzX_HCM += jp.E() - jp.pz(); // Sign + => -
       _eMpzX_HCM += jp.E() + jp.pz(); // Sign - => +
     }
     _momX_HCM = momX;
     _pX_HCM   = pX;
     _M2X      = _momX_HCM.mass2();
   
     // Y - side
     FourMomentum momY;
     for (const Particle& kp : pY) momY += kp.momentum();
     _momY_HCM = momY;
     _pY_HCM   = pY;
     _M2Y      = _momY_HCM.mass2();
 
     // Find variables related to LAB frame
     const LorentzTransform hcmboost   = diskin.boostHCM();
     const LorentzTransform hcminverse = hcmboost.inverse();
     _momX_LAB = hcminverse.transform(_momX_HCM);
     _momY_LAB = hcminverse.transform(_momY_HCM);
 
     // Find momenta in XCM frame. Note that it is HCM frame that is
     // boosted, resulting in a sign change later!
     const bool doXCM = (momX.betaVec().mod2() < 1.);
     if (doXCM) {
       const LorentzTransform xcmboost =
         LorentzTransform::mkFrameTransformFromBeta(momX.betaVec());
       _momX_XCM = xcmboost.transform(momX);
       _momY_XCM = xcmboost.transform(momY);
     }
 
     for (const Particle& jp : pX) {
       // Boost from HCM to LAB. 
       FourMomentum lab = hcminverse.transform(jp.momentum());
       _ePpzX_LAB += lab.E() + dir * lab.pz();
       _eMpzX_LAB += lab.E() - dir * lab.pz();
       Particle plab = jp;
       plab.setMomentum(lab);
       _pX_LAB.push_back(plab);
       // Set XCM. Note that since HCM frame is boosted to XCM frame,
       // we have a sign change
       if (doXCM) {
         const LorentzTransform xcmboost =
           LorentzTransform::mkFrameTransformFromBeta(_momX_HCM.betaVec());
         FourMomentum xcm = xcmboost.transform(jp.momentum());
         _ePpzX_XCM += xcm.E() - xcm.pz(); // Sign + => -
         _eMpzX_XCM += xcm.E() + xcm.pz(); // Sign - => +
         Particle pxcm = jp;
         pxcm.setMomentum(xcm);
         _pX_XCM.push_back(pxcm);
       }
     }
 
     for ( const Particle& jp : pY ) {
       // Boost from HCM to LAB
       FourMomentum lab = hcminverse.transform(jp.momentum());
       Particle plab = jp;
       plab.setMomentum(lab);
       _pY_LAB.push_back(plab);
       // Boost from HCM to XCM
       if (doXCM) {
         const LorentzTransform xcmboost =
           LorentzTransform::mkFrameTransformFromBeta(_momX_HCM.betaVec());
         FourMomentum xcm = xcmboost.transform(jp.momentum());
         Particle pxcm = jp;
         pxcm.setMomentum(xcm);
         _pY_XCM.push_back(pxcm);
       }
     }
 
     // Find t: Currently can only handle gap on proton side.
     // @TODO: Expand to also handle gap on photon side
     // Boost p from LAB to HCM frame to find t.
     FourMomentum proton = hcmboost.transform(diskin.beamHadron().momentum());
     FourMomentum pPom = proton - _momY_HCM;
     _t = pPom * pPom;
 
   }
 }
diff --git a/src/Projections/PrimaryParticles.cc b/src/Projections/PrimaryParticles.cc
--- a/src/Projections/PrimaryParticles.cc
+++ b/src/Projections/PrimaryParticles.cc
@@ -1,78 +1,78 @@
 #include <Rivet/Projections/PrimaryParticles.hh>
 #include <Rivet/Particle.hh>
 #include <Rivet/Event.hh>
 #include <Rivet/Tools/ParticleIdUtils.hh>
 #include <Rivet/Tools/ParticleName.hh>
 
 namespace Rivet {
 
 
   void PrimaryParticles::project(const Event& e)
   {
     _theParticles.clear(); // Clear cache
     bool open = _cuts == Cuts::open(); 
     for (auto p : HepMCUtils::particles(e.genEvent())) {
       if (isPrimary(p) && (open || _cuts->accept(Particle(p)))) 
 	_theParticles.push_back(Particle(*p));
     }
   }
 
   bool PrimaryParticles::isPrimary(ConstGenParticlePtr p) const
   {
     if(isIgnored(p))  return false;
     if(!isPrimaryPID(p)) return false;
 
     // Loop back over ancestors that are _not_ ignored 
     ConstGenParticlePtr m = p;
     while ((m = ancestor(m,true))) {
       if (isBeam(m)) return true;
       if (isPrimaryPID(m)) return false;
       if (!hasDecayed(m)) return false;
     }
     return true;
   }
   bool PrimaryParticles::isIgnored(ConstGenParticlePtr p) const
   {
     return (p->status()==0 || (p->status()>=11 && p->status()<=200));
   }
     
   bool PrimaryParticles::isPrimaryPID(ConstGenParticlePtr p) const
   {
-    int thisPID = PID::abspid(p->pdg_id());
+    int thisPID = abs(p->pdg_id());
     for(const auto pid : _pdgIds)
       if (thisPID == pid) return true;
     return false;
   }
 
   bool PrimaryParticles::isBeam(ConstGenParticlePtr p) const
   {
     // Pythia6 uses 3 for initial state
     return p && (p->status() == 3 || p->status() == 4); 
   }
 
   bool PrimaryParticles::hasDecayed(ConstGenParticlePtr p) const
   {
     return p && p->status() == 2;
   }
 
   ConstGenParticlePtr
   PrimaryParticles::ancestor(ConstGenParticlePtr p) const
   {
     ConstGenVertexPtr vtx = p->production_vertex();
     if (!vtx) return 0;
     
     auto parents = HepMCUtils::particles(vtx, Relatives::PARENTS);
     if ( parents.empty() ) return nullptr;
     return parents[0];
   }
   
   ConstGenParticlePtr
   PrimaryParticles::ancestor(ConstGenParticlePtr p, bool) const
   {
     ConstGenParticlePtr m = p;
     do {
       m = ancestor(m);
     } while (m && isIgnored(m));
     return m;
   }
 }
diff --git a/src/Projections/UndressBeamLeptons.cc b/src/Projections/UndressBeamLeptons.cc
--- a/src/Projections/UndressBeamLeptons.cc
+++ b/src/Projections/UndressBeamLeptons.cc
@@ -1,36 +1,36 @@
 // -*- C++ -*-
 #include "Rivet/Projections/UndressBeamLeptons.hh"
 
 namespace Rivet {
 
 
-  int UndressBeamLeptons::compare(const Projection & p) const {
+  CmpState UndressBeamLeptons::compare(const Projection & p) const {
     const UndressBeamLeptons & o =
       dynamic_cast<const UndressBeamLeptons &>(p);
     return cmp(_thetamax, o._thetamax) || mkNamedPCmp(o, "FS");
   }
 
 
   void UndressBeamLeptons::project(const Event& e) {
     Beam::project(e);
     if ( _thetamax <= 0.0 ) return;
     bool l1 = _theBeams.first.isChargedLepton();
     bool l2 = _theBeams.second.isChargedLepton();
     if ( !l1 && !l2 ) return;
     FourMomentum b1 = _theBeams.first.momentum();
     FourMomentum b2 = _theBeams.second.momentum();
     Vector3 b10 = b1.vector3();
     Vector3 b20 = b2.vector3();
     for ( auto p : apply<FinalState>(e, "FS").particles() ) {
       if ( p.pid() != PID::PHOTON ) continue;
       if ( p.momentum().angle(b10) < _thetamax )
         b1 -= p.momentum();
       if ( p.momentum().angle(b20) < _thetamax )
         b2 -= p.momentum();
     }
     _theBeams.first.setMomentum(b1);
     _theBeams.second.setMomentum(b2);
   }
 
 
 }