diff --git a/FixedOrderGen/include/EventGenerator.hh b/FixedOrderGen/include/EventGenerator.hh
index c696c72..e345a81 100644
--- a/FixedOrderGen/include/EventGenerator.hh
+++ b/FixedOrderGen/include/EventGenerator.hh
@@ -1,65 +1,65 @@
 /**
  *  \authors   The HEJ collaboration (see AUTHORS for details)
  *  \date      2019
  *  \copyright GPLv2 or later
  */
 #pragma once
 
 #include "HEJ/MatrixElement.hh"
 #include "HEJ/optional.hh"
 #include "HEJ/PDF.hh"
 #include "HEJ/RNG.hh"
 
 #include "Beam.hh"
 #include "Decay.hh"
 #include "JetParameters.hh"
 #include "Process.hh"
 #include "Status.hh"
 
 namespace HEJ{
   class Event;
   class HiggsCouplingSettings;
   class ScaleGenerator;
   class EWConstants;
 }
 
 //! Namespace for HEJ Fixed Order Generator
 namespace HEJFOG{
   class EventGenerator{
   public:
     EventGenerator(
         Process process,
         Beam beam,
         HEJ::ScaleGenerator scale_gen,
         JetParameters jets,
         int pdf_id,
         double subl_change,
         unsigned int subl_channels,
-        ParticlesDecayMap particles_decays,
+        ParticlesDecayMap particle_decays,
         HEJ::HiggsCouplingSettings Higgs_coupling,
         HEJ::EWConstants ew_parameters,
         HEJ::RNG & ran
     );
 
     HEJ::optional<HEJ::Event> gen_event();
 
     Status status() const {
       return status_;
     }
 
   private:
     HEJ::PDF pdf_;
     HEJ::MatrixElement ME_;
     HEJ::ScaleGenerator scale_gen_;
     Process process_;
     JetParameters jets_;
     Beam beam_;
     Status status_;
     double subl_change_;
     unsigned int subl_channels_;
-    ParticlesDecayMap particles_decays_;
+    ParticlesDecayMap particle_decays_;
     HEJ::EWConstants ew_parameters_;
     std::reference_wrapper<HEJ::RNG> ran_;
   };
 
 }
diff --git a/FixedOrderGen/include/PhaseSpacePoint.hh b/FixedOrderGen/include/PhaseSpacePoint.hh
index 0764045..16bcd9d 100644
--- a/FixedOrderGen/include/PhaseSpacePoint.hh
+++ b/FixedOrderGen/include/PhaseSpacePoint.hh
@@ -1,230 +1,230 @@
 /** \file      PhaseSpacePoint.hh
  *  \brief     Contains the PhaseSpacePoint Class
  *
  *  \authors   The HEJ collaboration (see AUTHORS for details)
  *  \date      2019
  *  \copyright GPLv2 or later
  */
 #pragma once
 
 #include <bitset>
 #include <vector>
 
 #include "HEJ/Event.hh"
 #include "HEJ/Particle.hh"
 #include "HEJ/PDF.hh"
 #include "HEJ/PDG_codes.hh"
 #include "HEJ/RNG.hh"
 
 #include "JetParameters.hh"
 #include "Decay.hh"
 #include "Status.hh"
 
 namespace HEJ{
   class EWConstants;
 }
 
 namespace HEJFOG{
   class Process;
 
   using HEJ::Particle;
   //! A point in resummation phase space
   class PhaseSpacePoint{
   public:
     //! Default PhaseSpacePoint Constructor
     PhaseSpacePoint() = delete;
 
     //! PhaseSpacePoint Constructor
     /**
      * @param proc                  The process to generate
      * @param jet_properties        Jet defintion & cuts
      * @param pdf                   The pdf set (used for sampling)
      * @param E_beam                Energie of the beam
      * @param subl_chance           Chance to turn a potentially unordered
      *                              emission into an actual one
      * @param subl_channels         Possible subleading channels.
      *                              see HEJFOG::Subleading
      * @param particle_properties   Properties of producted boson
      *
      * Initially, only FKL phase space points are generated. subl_chance gives
      * the change of turning one emissions into a subleading configuration,
      * i.e. either unordered or central quark/anti-quark pair. Unordered
      * emissions require that the most extremal emission in any direction is
      * a quark or anti-quark and the next emission is a gluon. Quark/anti-quark
      * pairs are only generated for W processes. At most one subleading
      * emission will be generated in this way.
      */
     PhaseSpacePoint(
       Process const & proc,
       JetParameters const & jet_properties,
       HEJ::PDF & pdf, double E_beam,
       double subl_chance,
       unsigned int subl_channels,
-      ParticlesDecayMap const & particles_decays,
+      ParticlesDecayMap const & particle_decays,
       HEJ::EWConstants const & ew_parameters,
       HEJ::RNG & ran
     );
 
     //! Get Weight Function
     /**
      * @returns        Weight of Event
      */
     double weight() const{
       return weight_;
     }
 
     Status status() const{
       return status_;
     }
 
     //! Get Incoming Function
     /**
      * @returns        Incoming Particles
      */
     std::array<Particle, 2> const & incoming() const{
       return incoming_;
     }
 
     //! Get Outgoing Function
     /**
      * @returns        Outgoing Particles
      */
     std::vector<Particle> const & outgoing() const{
       return outgoing_;
     }
 
     std::unordered_map<size_t, std::vector<Particle>> const & decays() const{
       return decays_;
     }
 
   private:
     /**
      * @internal
      * @brief Generate LO parton momentum
      *
      * @param count             Number of partons to generate
      * @param is_pure_jets      If true ensures momentum conservation in x and y
      * @param jet_param         Jet properties to fulfil
      * @param max_pt            max allowed pt for a parton (typically E_CMS)
      * @param ran               Random Number Generator
      *
      * @returns                 Momentum of partons
      *
      * Ensures that each parton is in its own jet.
      * Generation is independent of parton flavour. Output is sorted in rapidity.
      */
     std::vector<fastjet::PseudoJet> gen_LO_partons(
         int count, bool is_pure_jets,
         JetParameters const & jet_param,
         double max_pt,
         HEJ::RNG & ran
     );
     Particle gen_boson(
         HEJ::ParticleID bosonid, double mass, double width,
         HEJ::RNG & ran
     );
     template<class ParticleMomenta>
     fastjet::PseudoJet gen_last_momentum(
         ParticleMomenta const & other_momenta,
         double mass_square, double y
     ) const;
 
     bool jets_ok(
         std::vector<fastjet::PseudoJet> const & Born_jets,
         std::vector<fastjet::PseudoJet> const & partons
     ) const;
     /**
      * @internal
      * @brief Generate incoming partons according to the PDF
      *
      * @param uf                Scale used in the PDF
      */
     void reconstruct_incoming(
         Process const & proc, unsigned int subl_channels,
         HEJ::PDF & pdf, double E_beam,
         double uf,
         HEJ::RNG & ran
     );
     /**
      * @internal
      * @brief Returns list of all allowed initial states partons
      */
     std::array<std::bitset<11>,2> filter_partons(
         Process const & proc, unsigned int const subl_channels,
         HEJ::RNG & ran
     );
     HEJ::ParticleID generate_incoming_id(
         size_t beam_idx, double x, double uf, HEJ::PDF & pdf,
         std::bitset<11> allowed_partons, HEJ::RNG & ran
     );
 
     bool momentum_conserved(double ep) const;
 
     HEJ::Particle const & most_backward_FKL(
         std::vector<HEJ::Particle> const & partons
     ) const;
     HEJ::Particle const & most_forward_FKL(
         std::vector<HEJ::Particle> const & partons
     ) const;
     HEJ::Particle & most_backward_FKL(std::vector<HEJ::Particle> & partons) const;
     HEJ::Particle & most_forward_FKL(std::vector<HEJ::Particle> & partons) const;
     bool extremal_FKL_ok(
         std::vector<fastjet::PseudoJet> const & partons
     ) const;
     double random_normal(double stddev, HEJ::RNG & ran);
     /**
      * @internal
      * @brief Turns a FKL configuration into a subleading one
      *
      * @param chance            Change to switch to subleading configuration
      * @param channels          Allowed channels for subleading process
      * @param proc              Process to decide which subleading
      *                          configurations are allowed
      *
      * With a chance of "chance" the FKL configuration is either turned into
      * a unordered configuration or, for A/W/Z bosons, a configuration with
      * a central quark/anti-quark pair.
      */
     void maybe_turn_to_subl(double chance, unsigned int channels,
         Process const & proc, HEJ::RNG & ran);
     void turn_to_uno(bool can_be_uno_backward, bool can_be_uno_forward, HEJ::RNG & ran);
     void turn_to_qqx(bool allow_strange, HEJ::RNG & ran);
     //! decay where we select the decay channel
     std::vector<Particle> decay_boson(
         HEJ::Particle const & parent,
         std::vector<Decay> const & decays,
         HEJ::RNG & ran
     );
     //! generate decay products of a boson
     std::vector<Particle> decay_boson(
         HEJ::Particle const & parent,
         std::vector<HEJ::ParticleID> const & decays,
         HEJ::RNG & ran
     );
     /// @brief setup outgoing partons to ensure correct coupling to boson
     void couple_boson(HEJ::ParticleID boson, HEJ::RNG & ran);
     Decay select_decay_channel(
         std::vector<Decay> const & decays,
         HEJ::RNG & ran
     );
     double gen_hard_pt(
         int np, double ptmin, double ptmax, double y,
         HEJ::RNG & ran
     );
     double gen_soft_pt(int np, double ptmax, HEJ::RNG & ran);
     double gen_parton_pt(
         int count, JetParameters const & jet_param, double ptmax, double y,
         HEJ::RNG & ran
     );
 
     double weight_;
 
     Status status_;
 
     std::array<Particle, 2> incoming_;
     std::vector<Particle> outgoing_;
     //! Particle decays in the format {outgoing index, decay products}
     std::unordered_map<size_t, std::vector<Particle>> decays_;
   };
   HEJ::Event::EventData to_EventData(PhaseSpacePoint const & psp);
 }
diff --git a/FixedOrderGen/include/config.hh b/FixedOrderGen/include/config.hh
index 06a2487..d302168 100644
--- a/FixedOrderGen/include/config.hh
+++ b/FixedOrderGen/include/config.hh
@@ -1,45 +1,45 @@
 /**
  *  \authors   The HEJ collaboration (see AUTHORS for details)
  *  \date      2019
  *  \copyright GPLv2 or later
  */
 #pragma once
 
 #include "yaml-cpp/yaml.h"
 
 #include "HEJ/HiggsCouplingSettings.hh"
 #include "HEJ/optional.hh"
 #include "HEJ/config.hh"
 #include "HEJ/output_formats.hh"
 #include "HEJ/exceptions.hh"
 #include "HEJ/EWConstants.hh"
 
 #include "Beam.hh"
 #include "Decay.hh"
 #include "JetParameters.hh"
 #include "Process.hh"
 #include "UnweightSettings.hh"
 
 namespace HEJFOG{
 
   struct Config{
     Process process;
     int events;
     JetParameters jets;
     Beam beam;
     int pdf_id;
     double subleading_fraction;
     unsigned int subleading_channels; //! < see HEJFOG::Subleading
-    ParticlesDecayMap particles_decays;
+    ParticlesDecayMap particle_decays;
     YAML::Node analysis_parameters;
     HEJ::ScaleConfig scales;
     std::vector<HEJ::OutputFile> output;
     HEJ::RNGConfig rng;
     HEJ::HiggsCouplingSettings Higgs_coupling;
     HEJ::EWConstants ew_parameters;
     HEJ::optional<UnweightSettings> unweight;
   };
 
   Config load_config(std::string const & config_file);
 
 }
diff --git a/FixedOrderGen/src/EventGenerator.cc b/FixedOrderGen/src/EventGenerator.cc
index 3d2dfe6..8058577 100644
--- a/FixedOrderGen/src/EventGenerator.cc
+++ b/FixedOrderGen/src/EventGenerator.cc
@@ -1,90 +1,90 @@
 /**
  *  \authors   The HEJ collaboration (see AUTHORS for details)
  *  \date      2019
  *  \copyright GPLv2 or later
  */
 #include "EventGenerator.hh"
 
 #include "Process.hh"
 #include "Beam.hh"
 #include "JetParameters.hh"
 #include "PhaseSpacePoint.hh"
 
 #include "HEJ/config.hh"
 #include "HEJ/Event.hh"
 #include "HEJ/EWConstants.hh"
 
 namespace HEJFOG{
   EventGenerator::EventGenerator(
       Process process,
       Beam beam,
       HEJ::ScaleGenerator scale_gen,
       JetParameters jets,
       int pdf_id,
       double subl_change,
       unsigned int subl_channels,
-      ParticlesDecayMap particles_decays,
+      ParticlesDecayMap particle_decays,
       HEJ::HiggsCouplingSettings Higgs_coupling,
       HEJ::EWConstants ew_parameters,
       HEJ::RNG & ran
   ):
     pdf_{pdf_id, beam.particles[0], beam.particles[1]},
     ME_{
       [this](double mu){ return pdf_.Halphas(mu); },
       HEJ::MatrixElementConfig{
         false,
         std::move(Higgs_coupling),
         ew_parameters
       }
     },
     scale_gen_{std::move(scale_gen)},
     process_{std::move(process)},
     jets_{std::move(jets)},
     beam_{std::move(beam)},
     subl_change_{subl_change},
     subl_channels_{subl_channels},
-    particles_decays_{std::move(particles_decays)},
+    particle_decays_{std::move(particle_decays)},
     ew_parameters_{ew_parameters},
     ran_{ran}
   {
   }
 
   HEJ::optional<HEJ::Event> EventGenerator::gen_event(){
     HEJFOG::PhaseSpacePoint psp{
       process_,
       jets_,
       pdf_, beam_.energy,
       subl_change_, subl_channels_,
-      particles_decays_,
+      particle_decays_,
       ew_parameters_,
       ran_
     };
     status_ = psp.status();
     if(status_ != good) return {};
 
     HEJ::Event ev = scale_gen_(
         HEJ::Event{
           to_EventData( std::move(psp) ).cluster( jets_.def, jets_.min_pt)
         }
     );
 
     ev.generate_colours(ran_);
 
     const double shat = HEJ::shat(ev);
     const double xa = (ev.incoming()[0].E()-ev.incoming()[0].pz())/(2.*beam_.energy);
     const double xb = (ev.incoming()[1].E()+ev.incoming()[1].pz())/(2.*beam_.energy);
 
     // evaluate matrix element
     ev.parameters() *= ME_.tree(ev)/(shat*shat);
     // and PDFs
     ev.central().weight *= pdf_.pdfpt(0,xa,ev.central().muf, ev.incoming()[0].type);
     ev.central().weight *= pdf_.pdfpt(0,xb,ev.central().muf, ev.incoming()[1].type);
     for(size_t i = 0; i < ev.variations().size(); ++i){
       auto & var = ev.variations(i);
       var.weight *= pdf_.pdfpt(0,xa,var.muf, ev.incoming()[0].type);
       var.weight *= pdf_.pdfpt(0,xb,var.muf, ev.incoming()[1].type);
     }
     return ev;
   }
 
 }
diff --git a/FixedOrderGen/src/PhaseSpacePoint.cc b/FixedOrderGen/src/PhaseSpacePoint.cc
index 63c7e2b..3ff9ddb 100644
--- a/FixedOrderGen/src/PhaseSpacePoint.cc
+++ b/FixedOrderGen/src/PhaseSpacePoint.cc
@@ -1,693 +1,693 @@
 /**
  *  \authors   The HEJ collaboration (see AUTHORS for details)
  *  \date      2019
  *  \copyright GPLv2 or later
  */
 #include "PhaseSpacePoint.hh"
 
 #include <algorithm>
 
 #include "CLHEP/Vector/LorentzVector.h"
 
 #include "HEJ/Constants.hh"
 #include "HEJ/EWConstants.hh"
 #include "HEJ/exceptions.hh"
 #include "HEJ/kinematics.hh"
 #include "HEJ/Particle.hh"
 #include "HEJ/utility.hh"
 
 #include "Process.hh"
 #include "Subleading.hh"
 
 using namespace HEJ;
 
 namespace HEJFOG{
 
   static_assert(
       std::numeric_limits<double>::has_quiet_NaN,
       "no quiet NaN for double"
   );
   constexpr double NaN = std::numeric_limits<double>::quiet_NaN();
 
   HEJ::Event::EventData to_EventData(PhaseSpacePoint const & psp){
     HEJ::Event::EventData result;
     result.incoming = psp.incoming();
     assert(result.incoming.size() == 2);
     result.outgoing=psp.outgoing();
       // technically Event::EventData doesn't have to be sorted,
       // but PhaseSpacePoint should be anyway
     assert(
         std::is_sorted(
             begin(result.outgoing), end(result.outgoing),
             HEJ::rapidity_less{}
         )
     );
     assert(result.outgoing.size() >= 2);
     result.decays=psp.decays();
     result.parameters.central= {NaN, NaN, psp.weight() };
     return result;
   }
 
   namespace{
     bool can_swap_to_uno(
         HEJ::Particle const & p1, HEJ::Particle const & p2
     ){
       return is_parton(p1)
         && p1.type != pid::gluon
         && p2.type == pid::gluon;
     }
 
     size_t count_gluons(std::vector<Particle>::const_iterator first,
       std::vector<Particle>::const_iterator last){
       return std::count_if(first, last, [](Particle const & p)
         {return p.type == pid::gluon;});
     }
 
     /** assumes FKL configurations between first and last,
      * else there can be a quark in a non-extreme position
      * e.g. uno configuration gqg would pass
      */
     bool can_change_to_qqx(
       std::vector<Particle>::const_iterator first,
       std::vector<Particle>::const_iterator last){
       return 1 < count_gluons(first,last);
     }
     bool is_AWZ_proccess(Process const & proc){
       return proc.boson && is_AWZ_boson(*proc.boson);
     }
 
     bool is_up_type(Particle const & part){
       return HEJ::is_anyquark(part) && !(abs(part.type)%2);
     }
     bool is_down_type(Particle const & part){
       return HEJ::is_anyquark(part) && abs(part.type)%2;
     }
     bool can_couple_to_W(Particle const & part, pid::ParticleID const W_id){
       const int W_charge = W_id>0?1:-1;
       return abs(part.type)<5
         && ( (W_charge*part.type > 0 && is_up_type(part))
           || (W_charge*part.type < 0 && is_down_type(part)) );
     }
   }
 
   void PhaseSpacePoint::maybe_turn_to_subl(
       double chance,
       unsigned int const channels,
       Process const & proc,
       HEJ::RNG & ran
   ){
     if(proc.njets <= 2) return;
     assert(outgoing_.size() >= 2);
 
     // decide what kind of subleading process is allowed
     bool allow_uno = false;
     bool allow_strange = true;
     const size_t nout = outgoing_.size();
     const bool can_be_uno_backward = (channels&Subleading::uno)
       && can_swap_to_uno(outgoing_[0], outgoing_[1]);
     const bool can_be_uno_forward = (channels&Subleading::uno)
       && can_swap_to_uno(outgoing_[nout-1], outgoing_[nout-2]);
     allow_uno = can_be_uno_backward || can_be_uno_forward;
 
     bool allow_qqx = false;
     if(is_AWZ_proccess(proc)) {
       allow_qqx = (channels&Subleading::qqx)
         && can_change_to_qqx(outgoing_.cbegin(), outgoing_.cend());
       if(std::none_of(outgoing_.cbegin(), outgoing_.cend(),
           [&proc](Particle const & p){ return can_couple_to_W(p, *proc.boson);})) {
         // enforce qqx if A/W/Z can't couple somewhere else
         assert(allow_qqx);
         allow_uno = false;
         chance = 1.;
         // strange not allowed for W
         if(abs(*proc.boson)== pid::Wp) allow_strange = false;
       }
     }
 
     if(!allow_uno && !allow_qqx) return;
     if(ran.flat() < chance){
       weight_ /= chance;
       if(allow_uno && !allow_qqx){
           turn_to_uno(can_be_uno_backward, can_be_uno_forward, ran);
       } else if (!allow_uno && allow_qqx) {
         turn_to_qqx(allow_strange, ran);
       } else {
         assert( allow_uno && allow_qqx);
         if(ran.flat() < 0.5) turn_to_uno(can_be_uno_backward, can_be_uno_forward, ran);
         else turn_to_qqx(allow_strange, ran);
         weight_ *= 2.;
       }
     } else weight_ /= 1 - chance;
 
   }
 
   void PhaseSpacePoint::turn_to_uno(
       const bool can_be_uno_backward, const bool can_be_uno_forward,
       HEJ::RNG & ran
   ){
     if(!can_be_uno_backward && !can_be_uno_forward) return;
     const size_t nout = outgoing_.size();
     if(can_be_uno_backward && can_be_uno_forward){
       if(ran.flat() < 0.5){
         std::swap(outgoing_[0].type, outgoing_[1].type);
       } else {
         std::swap(outgoing_[nout-1].type, outgoing_[nout-2].type);
       }
       weight_ *= 2.;
     } else if(can_be_uno_backward){
       std::swap(outgoing_[0].type, outgoing_[1].type);
     } else {
       assert(can_be_uno_forward);
       std::swap(outgoing_[nout-1].type, outgoing_[nout-2].type);
     }
   }
 
   void PhaseSpacePoint::turn_to_qqx(const bool allow_strange, HEJ::RNG & ran){
     /// find first and last gluon in FKL chain
     auto first = std::find_if(outgoing_.begin(), outgoing_.end(),
       [](Particle const & p){return p.type == pid::gluon;});
     std::vector<Particle*> FKL_gluons;
     for(auto p = first; p!=outgoing_.end(); ++p){
       if(p->type == pid::gluon) FKL_gluons.push_back(&*p);
       else if(is_anyquark(*p)) break;
     }
     const size_t ng = FKL_gluons.size();
     if(ng < 2)
       throw std::logic_error("not enough gluons to create qqx");
     // select flavour of quark
     const double r1 = 2.*ran.flat()-1.;
     const double max_flavour = allow_strange?n_f:n_f-1;
     weight_ *= max_flavour*2;
     int flavour = pid::down + std::floor(std::abs(r1)*max_flavour);
     flavour*=r1<0.?-1:1;
     // select gluon for switch
     const size_t idx = floor((ng-1) * ran.flat());
     weight_ *= (ng-1);
     FKL_gluons[idx]->type = ParticleID(flavour);
     FKL_gluons[idx+1]->type = ParticleID(-flavour);
   }
 
   template<class ParticleMomenta>
   fastjet::PseudoJet PhaseSpacePoint::gen_last_momentum(
       ParticleMomenta const & other_momenta,
       const double mass_square, const double y
   ) const {
     std::array<double,2> pt{0.,0.};
     for (auto const & p: other_momenta) {
       pt[0]-= p.px();
       pt[1]-= p.py();
     }
 
     const double mperp = sqrt(pt[0]*pt[0]+pt[1]*pt[1]+mass_square);
     const double pz=mperp*sinh(y);
     const double E=mperp*cosh(y);
 
     return {pt[0], pt[1], pz, E};
   }
 
   namespace {
     //! adds a particle to target (in correct rapidity ordering)
     //! @returns    positon of insertion
     auto insert_particle(std::vector<HEJ::Particle> & target,
       HEJ::Particle && particle
     ){
       const auto pos = std::upper_bound(
           begin(target),end(target),particle,rapidity_less{}
       );
       target.insert(pos, std::move(particle));
       return pos;
     }
   }
 
   PhaseSpacePoint::PhaseSpacePoint(
     Process const & proc,
     JetParameters const & jet_param,
     HEJ::PDF & pdf, double E_beam,
     double const subl_chance,
     unsigned int const subl_channels,
-    ParticlesDecayMap const & particles_decays,
+    ParticlesDecayMap const & particle_decays,
     HEJ::EWConstants const & ew_parameters,
     HEJ::RNG & ran
   )
   {
     // auto proc{ proc_in }; // @TODO remove
     assert(proc.njets >= 2);
     status_ = good;
     weight_ = 1;
 
     const int nout = proc.njets + (proc.boson?1:0) + proc.boson_decay.size();
     outgoing_.reserve(nout);
 
     // generate parton momenta
     const bool is_pure_jets = (nout == proc.njets);
     auto partons = gen_LO_partons(
         proc.njets, is_pure_jets, jet_param, E_beam, ran
     );
     // pre fill flavour with gluons
     for(auto&& p_out: partons) {
       outgoing_.emplace_back(Particle{pid::gluon, std::move(p_out), {}});
     }
     if(status_ != good) return;
 
     if(proc.boson){ // decay boson
       const auto & boson_prop = ew_parameters.prop(*proc.boson) ;
       auto boson{ gen_boson(*proc.boson, boson_prop.mass, boson_prop.width, ran) };
       const auto pos{insert_particle(outgoing_, std::move(boson))};
       const size_t boson_idx = std::distance(begin(outgoing_), pos);
-      const auto & boson_decay = particles_decays.find(*proc.boson);
+      const auto & boson_decay = particle_decays.find(*proc.boson);
       if( !proc.boson_decay.empty() ){ // decay given in proc
         decays_.emplace(
             boson_idx,
             decay_boson(outgoing_[boson_idx], proc.boson_decay, ran)
         );
-      } else if( boson_decay != particles_decays.end()
+      } else if( boson_decay != particle_decays.end()
                 && !boson_decay->second.empty() ){ // decay given explicitly
         decays_.emplace(
             boson_idx,
             decay_boson(outgoing_[boson_idx], boson_decay->second, ran)
         );
       }
     }
     // normalisation of momentum-conserving delta function
     weight_ *= pow(2*M_PI, 4);
 
     /** @TODO
      *  uf (jet_param.min_pt) doesn't correspond to our final scale choice.
      *  The HEJ scale generators currently expect a full event as input,
      *  so fixing this is not completely trivial
      */
     reconstruct_incoming(proc, subl_channels, pdf, E_beam, jet_param.min_pt, ran);
     if(status_ != good) return;
     // set outgoing states
     most_backward_FKL(outgoing_).type = incoming_[0].type;
     most_forward_FKL(outgoing_).type = incoming_[1].type;
 
     maybe_turn_to_subl(subl_chance, subl_channels, proc, ran);
 
     if(proc.boson) couple_boson(*proc.boson, ran);
   }
 
   double PhaseSpacePoint::gen_hard_pt(
       int np , double ptmin, double ptmax, double y,
       HEJ::RNG & ran
   ) {
     // heuristic parameters for pt sampling
     const double ptpar = ptmin + np/5.;
     const double arg_small_y = atan((ptmax - ptmin)/ptpar);
     const double y_cut = 3.;
 
     const double r1 = ran.flat();
     if(y < y_cut){
       const double pt = ptmin + ptpar*tan(r1*arg_small_y);
       const double temp = cos(r1*arg_small_y);
       weight_ *= pt*ptpar*arg_small_y/(temp*temp);
       return pt;
     }
 
     const double ptpar2 = ptpar/(1 + 5*(y-y_cut));
     const double temp = 1. - std::exp((ptmin-ptmax)/ptpar2);
     const double pt = ptmin - ptpar2*std::log(1-r1*temp);
     weight_ *= pt*ptpar2*temp/(1-r1*temp);
     return pt;
   }
 
   double PhaseSpacePoint::gen_soft_pt(int np, double max_pt, HEJ::RNG & ran) {
     constexpr double ptpar = 4.;
 
     const double r = ran.flat();
     const double pt = max_pt + ptpar/np*std::log(r);
     weight_ *= pt*ptpar/(np*r);
     return pt;
   }
 
   double PhaseSpacePoint::gen_parton_pt(
       int count, JetParameters const & jet_param, double max_pt, double y,
       HEJ::RNG & ran
   ) {
     constexpr double p_small_pt = 0.02;
 
     if(! jet_param.peak_pt) {
        return gen_hard_pt(count, jet_param.min_pt, max_pt, y, ran);
     }
     const double r = ran.flat();
     if(r > p_small_pt) {
       weight_ /= 1. - p_small_pt;
       return gen_hard_pt(count, *jet_param.peak_pt, max_pt, y, ran);
     }
     weight_ /= p_small_pt;
     const double pt =  gen_soft_pt(count, *jet_param.peak_pt, ran);
     if(pt < jet_param.min_pt) {
       weight_=0.0;
       status_ = not_enough_jets;
       return jet_param.min_pt;
     }
     return pt;
   }
 
   std::vector<fastjet::PseudoJet> PhaseSpacePoint::gen_LO_partons(
       int np, bool is_pure_jets,
       JetParameters const & jet_param,
       double max_pt,
       HEJ::RNG & ran
   ){
     if (np<2) throw std::invalid_argument{"Not enough partons in gen_LO_partons"};
 
     weight_ /= pow(16.*pow(M_PI,3),np);
     weight_ /= std::tgamma(np+1); //remove rapidity ordering
     std::vector<fastjet::PseudoJet> partons;
     partons.reserve(np);
     for(int i = 0; i < np; ++i){
       const double y = -jet_param.max_y + 2*jet_param.max_y*ran.flat();
       weight_ *= 2*jet_param.max_y;
 
       const bool is_last_parton = i+1 == np;
       if(is_pure_jets && is_last_parton) {
         constexpr double parton_mass_sq = 0.;
         partons.emplace_back(gen_last_momentum(partons, parton_mass_sq, y));
         break;
       }
 
       const double phi = 2*M_PI*ran.flat();
       weight_ *= 2.0*M_PI;
 
       const double pt = gen_parton_pt(np, jet_param, max_pt, y, ran);
       if(weight_ == 0.0) return {};
 
       partons.emplace_back(fastjet::PtYPhiM(pt, y, phi));
       assert(jet_param.min_pt <= partons[i].pt());
       assert(partons[i].pt() <= max_pt+1e-5);
     }
     // Need to check that at LO, the number of jets = number of partons;
     fastjet::ClusterSequence cs(partons, jet_param.def);
     auto cluster_jets=cs.inclusive_jets(jet_param.min_pt);
     if (cluster_jets.size()!=unsigned(np)){
       weight_=0.0;
       status_ = not_enough_jets;
       return {};
     }
 
     std::sort(begin(partons), end(partons), rapidity_less{});
 
     return partons;
   }
 
   Particle PhaseSpacePoint::gen_boson(
       HEJ::ParticleID bosonid, double mass, double width,
       HEJ::RNG & ran
   ){
     // Usual phase space measure
     weight_ /= 16.*pow(M_PI, 3);
 
     // Generate a y Gaussian distributed around 0
     /// @TODO check magic numbers for different boson Higgs
     /// @TODO better sampling for W
     const double stddev_y = 1.6;
     const double y = random_normal(stddev_y, ran);
     const double r1 = ran.flat();
     const double s_boson = mass*(
         mass + width*tan(M_PI/2.*r1 + (r1-1.)*atan(mass/width))
     );
     // off-shell s_boson sampling, compensates for Breit-Wigner
     /// @TODO use a flag instead
     if(abs(bosonid) == pid::Wp){
       weight_/=M_PI*M_PI*8.;
       weight_*= mass*width*( M_PI+2.*atan(mass/width) )
               / ( 1. + cos( M_PI*r1 + 2.*(r1-1.)*atan(mass/width) ) );
     }
 
     auto p = gen_last_momentum(outgoing_, s_boson, y);
 
     return Particle{bosonid, std::move(p), {}};
   }
 
   Particle const & PhaseSpacePoint::most_backward_FKL(
       std::vector<Particle> const & partons
   ) const{
     if(!HEJ::is_parton(partons[0])) return partons[1];
     return partons[0];
   }
 
   Particle const & PhaseSpacePoint::most_forward_FKL(
       std::vector<Particle> const & partons
   ) const{
     const size_t last_idx = partons.size() - 1;
     if(!HEJ::is_parton(partons[last_idx])) return partons[last_idx-1];
     return partons[last_idx];
   }
 
   Particle & PhaseSpacePoint::most_backward_FKL(
       std::vector<Particle> & partons
   ) const{
     if(!HEJ::is_parton(partons[0])) return partons[1];
     return partons[0];
   }
 
   Particle & PhaseSpacePoint::most_forward_FKL(
       std::vector<Particle> & partons
   ) const{
     const size_t last_idx = partons.size() - 1;
     if(!HEJ::is_parton(partons[last_idx])) return partons[last_idx-1];
     return partons[last_idx];
   }
 
   namespace {
     /// partons are ordered: even = anti, 0 = gluon
     ParticleID index_to_pid(size_t i){
       if(!i) return pid::gluon;
       return static_cast<ParticleID>(i%2?(i+1)/2:-i/2);
     }
 
     /// partons are ordered: even = anti, 0 = gluon
     size_t pid_to_index(ParticleID id){
       if(id==pid::gluon) return 0;
       return id>0?id*2-1:abs(id)*2;
     }
 
     std::bitset<11> init_allowed(ParticleID const id){
       if(abs(id) == pid::proton)
         return ~0;
       std::bitset<11> out = 0;
       if(is_parton(id))
         out[pid_to_index(id)] = 1;
       return out;
     }
 
     /// decides which "index" (see index_to_pid) are allowed for process
     std::bitset<11> allowed_quarks(ParticleID const boson){
       std::bitset<11> allowed = ~0;
       if(abs(boson) == pid::Wp){
         // special case W:
         // Wp: anti-down or up-type quark, no b/t -> 0001100110(1) = 205
         // Wm: down or anti-up-type quark, no b/t -> 0010011001(1) = 307
         allowed = boson>0?205:307;
       }
       return allowed;
     }
   }
 
   /**
    * checks which partons are allowed as initial state:
    * 1. only allow what is given in the Runcard (p -> all)
    * 2. A/W/Z require something to couple to
    *  a) no qqx => no incoming gluon
    *  b) 2j     => no incoming gluon
    *  c) 3j     => can couple OR is gluon => 2 gluons become qqx later
    */
   std::array<std::bitset<11>,2> PhaseSpacePoint::filter_partons(
       Process const & proc, unsigned int const subl_channels, HEJ::RNG & ran
   ){
     std::array<std::bitset<11>,2> allowed_partons{
         init_allowed(proc.incoming[0]),
         init_allowed(proc.incoming[1])
       };
     bool const allow_qqx = subl_channels&Subleading::qqx;
     // special case A/W/Z
     if(is_AWZ_proccess(proc) && ((proc.njets < 4) || !allow_qqx)){
       // all possible incoming states
       auto allowed(allowed_quarks(*proc.boson));
       if(proc.njets == 2 || !allow_qqx) allowed[0]=0;
 
       // possible states per leg
       std::array<std::bitset<11>,2> const maybe_partons{
         allowed_partons[0]&allowed, allowed_partons[1]&allowed};
 
       if(maybe_partons[0].any() && maybe_partons[1].any()){
         // two options to get allowed initial state => choose one at random
         const size_t idx = ran.flat() < 0.5;
         allowed_partons[idx] = maybe_partons[idx];
         // else choose the possible
       } else if(maybe_partons[0].any()) {
         allowed_partons[0] = maybe_partons[0];
       } else if(maybe_partons[1].any()) {
         allowed_partons[1] = maybe_partons[1];
       } else{
         throw std::invalid_argument{"Incoming state not allowed."};
       }
     }
     return allowed_partons;
   }
 
   void PhaseSpacePoint::reconstruct_incoming(
       Process const & proc, unsigned int const subl_channels,
       HEJ::PDF & pdf, double E_beam,
       double uf,
       HEJ::RNG & ran
   ){
     std::tie(incoming_[0].p, incoming_[1].p) = incoming_momenta(outgoing_);
     // calculate xa, xb
     const double sqrts=2*E_beam;
     const double xa=(incoming_[0].p.e()-incoming_[0].p.pz())/sqrts;
     const double xb=(incoming_[1].p.e()+incoming_[1].p.pz())/sqrts;
     // abort if phase space point is outside of collider energy reach
     if (xa>1. || xb>1.){
       weight_=0;
       status_ = too_much_energy;
       return;
     }
     auto const & ids = proc.incoming;
     std::array<std::bitset<11>,2> allowed_partons(
       filter_partons(proc, subl_channels, ran));
     for(size_t i = 0; i < 2; ++i){
       if(ids[i] == pid::proton || ids[i] == pid::p_bar){
       // pick ids according to pdfs
         incoming_[i].type =
           generate_incoming_id(i, i?xb:xa, uf, pdf, allowed_partons[i], ran);
       } else {
         assert(allowed_partons[i][pid_to_index(ids[i])]);
         incoming_[i].type = ids[i];
       }
     }
     assert(momentum_conserved(1e-7));
   }
 
   HEJ::ParticleID PhaseSpacePoint::generate_incoming_id(
       size_t const beam_idx, double const x, double const uf,
       HEJ::PDF & pdf, std::bitset<11> allowed_partons, HEJ::RNG & ran
   ){
     std::array<double,11> pdf_wt;
     pdf_wt[0] = allowed_partons[0]?fabs(pdf.pdfpt(beam_idx,x,uf,pid::gluon)):0.;
     double pdftot = pdf_wt[0];
     for(size_t i = 1; i < pdf_wt.size(); ++i){
       pdf_wt[i] = allowed_partons[i]?4./9.*fabs(pdf.pdfpt(beam_idx,x,uf,index_to_pid(i))):0;
       pdftot += pdf_wt[i];
     }
     const double r1 = pdftot * ran.flat();
     double sum = 0;
     for(size_t i=0; i < pdf_wt.size(); ++i){
       if (r1 < (sum+=pdf_wt[i])){
         weight_*= pdftot/pdf_wt[i];
         return index_to_pid(i);
       }
     }
     std::cerr << "Error in choosing incoming parton: "<<x<<" "<<uf<<" "
       <<sum<<" "<<pdftot<<" "<<r1<<std::endl;
     throw std::logic_error{"Failed to choose parton flavour"};
   }
 
   void PhaseSpacePoint::couple_boson(
     HEJ::ParticleID const boson, HEJ::RNG & ran
   ){
     if(abs(boson) != pid::Wp) return; // only matters for W
     /// @TODO this could be use to sanity check gamma and Z
 
     // find all possible quarks
     std::vector<Particle*> allowed_parts;
     for(auto & part: outgoing_){
       // Wp -> up OR anti-down, Wm -> anti-up OR down, no bottom
       if ( can_couple_to_W(part, boson) )
         allowed_parts.push_back(&part);
     }
     if(allowed_parts.size() == 0){
       throw std::logic_error{"Found no parton for coupling with boson"};
     }
 
     // select one and flip it
     size_t idx = 0;
     if(allowed_parts.size() > 1){
       /// @TODO more efficient sampling
       ///       old code: probability[i] = exp(parton[i].y - W.y)
       idx = floor(ran.flat()*allowed_parts.size());
       weight_ *= allowed_parts.size();
     }
     const int W_charge = boson>0?1:-1;
     allowed_parts[idx]->type =
       static_cast<ParticleID>( allowed_parts[idx]->type - W_charge );
   }
 
   double PhaseSpacePoint::random_normal(
       double stddev,
       HEJ::RNG & ran
   ){
     const double r1 = ran.flat();
     const double r2 = ran.flat();
     const double lninvr1 = -log(r1);
     const double result = stddev*sqrt(2.*lninvr1)*cos(2.*M_PI*r2);
     weight_ *= exp(result*result/(2*stddev*stddev))*sqrt(2.*M_PI)*stddev;
     return result;
   }
 
   bool PhaseSpacePoint::momentum_conserved(double ep) const{
     fastjet::PseudoJet diff;
     for(auto const & in: incoming()) diff += in.p;
     for(auto const & out: outgoing()) diff -= out.p;
     return nearby_ep(diff, fastjet::PseudoJet{}, ep);
   }
 
   Decay PhaseSpacePoint::select_decay_channel(
       std::vector<Decay> const & decays,
       HEJ::RNG & ran
   ){
     double br_total = 0.;
     for(auto const & decay: decays) br_total += decay.branching_ratio;
     // adjust weight
     // this is given by (channel branching ratio)/(chance to pick channel)
     // where (chance to pick channel) =
     //       (channel branching ratio)/(total branching ratio)
     weight_ *= br_total;
     if(decays.size()==1) return decays.front();
     const double r1 = br_total*ran.flat();
     double br_sum = 0.;
     for(auto const & decay: decays){
       br_sum += decay.branching_ratio;
       if(r1 < br_sum) return decay;
     }
     throw std::logic_error{"unreachable"};
   }
 
   std::vector<Particle> PhaseSpacePoint::decay_boson(
       HEJ::Particle const & parent,
       std::vector<Decay> const & decays,
       HEJ::RNG & ran
   ){
     const auto channel = select_decay_channel(decays, ran);
     return decay_boson(parent, channel.products, ran);
   }
 
   std::vector<Particle> PhaseSpacePoint::decay_boson(
       HEJ::Particle const & parent,
       std::vector<HEJ::ParticleID> const & decays,
       HEJ::RNG & ran
   ){
     if(decays.size() != 2){
       throw HEJ::not_implemented{
         "only decays into two particles are implemented"
       };
     }
     std::vector<Particle> decay_products(decays.size());
     for(size_t i = 0; i < decays.size(); ++i){
       decay_products[i].type = decays[i];
     }
     // choose polar and azimuth angle in parent rest frame
     const double E = parent.m()/2;
     const double theta = 2.*M_PI*ran.flat();
     const double cos_phi = 2.*ran.flat()-1.;
     const double sin_phi = sqrt(1. - cos_phi*cos_phi);  // Know 0 < phi < pi
     const double px = E*cos(theta)*sin_phi;
     const double py = E*sin(theta)*sin_phi;
     const double pz = E*cos_phi;
     decay_products[0].p.reset(px, py, pz, E);
     decay_products[1].p.reset(-px, -py, -pz, E);
     for(auto & particle: decay_products) particle.p.boost(parent.p);
     return decay_products;
   }
 }
diff --git a/FixedOrderGen/src/config.cc b/FixedOrderGen/src/config.cc
index aa91355..447f6ab 100644
--- a/FixedOrderGen/src/config.cc
+++ b/FixedOrderGen/src/config.cc
@@ -1,413 +1,413 @@
 /**
  *  \authors   The HEJ collaboration (see AUTHORS for details)
  *  \date      2019
  *  \copyright GPLv2 or later
  */
 #include "config.hh"
 
 #include <cctype>
 
 #include "Subleading.hh"
 
 #include "HEJ/config.hh"
 #include "HEJ/YAMLreader.hh"
 
 namespace HEJFOG{
   using HEJ::set_from_yaml;
   using HEJ::set_from_yaml_if_defined;
   using HEJ::pid::ParticleID;
 
   namespace{
     //! Get YAML tree of supported options
     /**
      * The configuration file is checked against this tree of options
      * in assert_all_options_known.
      */
     YAML::Node const & get_supported_options(){
       const static YAML::Node supported = [](){
         YAML::Node supported;
         static const auto opts = {
           "process", "events", "subleading fraction","subleading channels",
           "scales", "scale factors", "max scale ratio", "pdf", "vev",
           "event output", "analysis", "import scales"
         };
         // add subnodes to "supported" - the assigned value is irrelevant
         for(auto && opt: opts) supported[opt] = "";
         for(auto && jet_opt: {"min pt", "peak pt", "algorithm", "R", "max rapidity"}){
           supported["jets"][jet_opt] = "";
         }
         for(auto && particle_type: {"Higgs", "W", "Z"}){
           for(auto && particle_opt: {"mass", "width"}){
             supported["particle properties"][particle_type][particle_opt] = "";
           }
         }
         for(auto && particle_type: {"Higgs", "Wp", "W+", "Wm", "W-", "Z"}){
           for(auto && particle_opt: {"into", "branching ratio"}){
             supported["decays"][particle_type][particle_opt] = "";
           }
         }
         for(auto && opt: {"mt", "use impact factors", "include bottom", "mb"}){
           supported["Higgs coupling"][opt] = "";
         }
         for(auto && beam_opt: {"energy", "particles"}){
           supported["beam"][beam_opt] = "";
         }
         for(auto && unweight_opt: {"sample size", "max deviation"}){
           supported["unweight"][unweight_opt] = "";
         }
         for(auto && opt: {"name", "seed"}){
           supported["random generator"][opt] = "";
         }
         return supported;
       }();
       return supported;
     }
 
     JetParameters get_jet_parameters(
         YAML::Node const & node, std::string const & entry
     ){
       const auto p = HEJ::get_jet_parameters(node, entry);
       JetParameters result;
       result.def = p.def;
       result.min_pt = p.min_pt;
       set_from_yaml(result.max_y, node, entry, "max rapidity");
       set_from_yaml_if_defined(result.peak_pt, node, entry, "peak pt");
       if(result.peak_pt && *result.peak_pt <= result.min_pt)
         throw std::invalid_argument{
           "Value of option 'peak pt' has to be larger than 'min pt'."
         };
       return result;
     }
 
     Beam get_Beam(
         YAML::Node const & node, std::string const & entry
     ){
       Beam beam;
       std::vector<HEJ::ParticleID> particles;
       set_from_yaml(beam.energy, node, entry, "energy");
       set_from_yaml_if_defined(particles, node, entry, "particles");
       if(! particles.empty()){
         for(HEJ::ParticleID particle: particles){
           if(particle != HEJ::pid::p && particle != HEJ::pid::p_bar){
             throw std::invalid_argument{
               "Unsupported value in option " + entry + ": particles:"
               " only proton ('p') and antiproton ('p_bar') beams are supported"
             };
           }
         }
         if(particles.size() != 2){
           throw std::invalid_argument{"Not exactly two beam particles"};
         }
         beam.particles.front() = particles.front();
         beam.particles.back() = particles.back();
       }
       return beam;
     }
 
     std::vector<std::string> split(
         std::string const & str, std::string const & delims
     ){
       std::vector<std::string> result;
       for(size_t begin, end = 0; end != str.npos;){
         begin = str.find_first_not_of(delims, end);
         if(begin == str.npos) break;
         end = str.find_first_of(delims, begin + 1);
         result.emplace_back(str.substr(begin, end - begin));
       }
       return result;
     }
 
     std::invalid_argument invalid_incoming(std::string const & what){
       return std::invalid_argument{
         "Incoming particle type " + what + " not supported,"
         " incoming particles have to be 'p', 'p_bar' or partons"
       };
     }
 
     std::invalid_argument invalid_outgoing(std::string const & what){
       return std::invalid_argument{
         "Outgoing particle type " + what + " not supported,"
         " outgoing particles have to be 'j', 'photon', 'H', 'Wm', 'Wp', 'e-', 'e+', 'nu_e', 'nu_e_bar'"
       };
     }
 
     HEJ::ParticleID reconstruct_boson_id(
       std::vector<HEJ::ParticleID> const & ids
     ){
       assert(ids.size()==2);
       const int pidsum = ids[0] + ids[1];
       if(pidsum == +1) {
         assert(HEJ::is_antilepton(ids[0]));
         if(HEJ::is_antineutrino(ids[0])) {
           throw HEJ::not_implemented{"lepton-flavour violating final state"};
         }
         assert(HEJ::is_neutrino(ids[1]));
         // charged antilepton + neutrino means we had a W+
         return HEJ::pid::Wp;
       }
       if(pidsum == -1) {
         assert(HEJ::is_antilepton(ids[0]));
         if(HEJ::is_neutrino(ids[1])) {
           throw HEJ::not_implemented{"lepton-flavour violating final state"};
         }
         assert(HEJ::is_antineutrino(ids[0]));
         // charged lepton + antineutrino means we had a W-
         return HEJ::pid::Wm;
       }
       throw HEJ::not_implemented{
         "final state with leptons "+HEJ::name(ids[0])+" and "+HEJ::name(ids[1])
           +" not supported"
       };
     }
 
     Process get_process(
         YAML::Node const & node, std::string const & entry
     ){
       Process result;
 
       std::string process_string;
       set_from_yaml(process_string, node, entry);
       assert(! process_string.empty());
       const auto particles = split(process_string, " \n\t\v=>");
       if(particles.size() < 3){
         throw std::invalid_argument{
           "Bad format in option process: '" + process_string
           + "', expected format is 'in1 in2 => out1 ...'"
         };
       }
       result.incoming.front() = HEJ::to_ParticleID(particles[0]);
       result.incoming.back() = HEJ::to_ParticleID(particles[1]);
 
       for(size_t i = 0; i < result.incoming.size(); ++i){
         const HEJ::ParticleID in = result.incoming[i];
         if(
             in != HEJ::pid::proton && in != HEJ::pid::p_bar
             && !HEJ::is_parton(in)
         ){
           throw invalid_incoming(particles[i]);
         }
       }
       result.njets = 0;
       for(size_t i = result.incoming.size(); i < particles.size(); ++i){
         assert(! particles[i].empty());
         if(particles[i] == "j") ++result.njets;
         else if(std::isdigit(particles[i].front())
                 && particles[i].back() == 'j')
           result.njets += std::stoi(particles[i]);
         else{
           const auto pid = HEJ::to_ParticleID(particles[i]);
           if(pid==HEJ::pid::Higgs || pid==HEJ::pid::Wp || pid==HEJ::pid::Wm){
             if(result.boson)
               throw std::invalid_argument{
                 "More than one outgoing boson is not supported"
                   };
             if(!result.boson_decay.empty())
               throw std::invalid_argument{
                 "Production of a boson together with a lepton is not supported"
               };
             result.boson = pid;
           } else if (HEJ::is_anylepton(pid)){
             // Do not accept more leptons, if two leptons are already mentioned
             if( result.boson_decay.size()>=2 )
               throw std::invalid_argument{"Too many leptons provided"};
             if(result.boson)
               throw std::invalid_argument{
                 "Production of a lepton together with a boson is not supported"
               };
             result.boson_decay.emplace_back(pid);
           } else {
             throw invalid_outgoing(particles[i]);
           }
         }
       }
       if(result.njets < 2){
         throw std::invalid_argument{
           "Process has to include at least two jets ('j')"
         };
       }
       if(!result.boson_decay.empty()){
         std::sort(begin(result.boson_decay),end(result.boson_decay));
         assert(!result.boson);
         result.boson = reconstruct_boson_id(result.boson_decay);
       }
       return result;
     }
 
     HEJFOG::Subleading to_subleading_channel(YAML::Node const & yaml){
       std::string name;
       using namespace HEJFOG::channels;
       set_from_yaml(name, yaml);
       if(name == "none")
         return none;
       if(name == "all")
         return all;
       if(name == "unordered" || name == "uno")
         return uno;
       if(name == "qqx")
         return qqx;
       throw HEJ::unknown_option("Unknown subleading channel '"+name+"'");
     }
 
     unsigned int get_subleading_channels(YAML::Node const & node){
       using YAML::NodeType;
       using namespace HEJFOG::channels;
       // all channels allowed by default
       if(!node) return all;
       switch(node.Type()){
       case NodeType::Undefined:
         return  all;
       case NodeType::Null:
         return none;
       case NodeType::Scalar:
         return to_subleading_channel(node);
       case NodeType::Map:
         throw HEJ::invalid_type{"map is not a valid option for subleading channels"};
       case NodeType::Sequence:
         unsigned int channels = HEJFOG::Subleading::none;
         for(auto && channel_node: node){
           channels |= get_subleading_channels(channel_node);
         }
         return channels;
       }
       throw std::logic_error{"unreachable"};
     }
 
     Decay get_decay(YAML::Node const & node){
       Decay decay;
       set_from_yaml(decay.products, node, "into");
       decay.branching_ratio=1;
       set_from_yaml_if_defined(decay.branching_ratio, node, "branching ratio");
       return decay;
     }
 
     std::vector<Decay> get_decays(YAML::Node const & node){
       using YAML::NodeType;
       if(!node) return {};
       switch(node.Type()){
       case NodeType::Null:
       case NodeType::Undefined:
         return {};
       case NodeType::Scalar:
         throw HEJ::invalid_type{"value is not a list of decays"};
       case NodeType::Map:
         return {get_decay(node)};
       case NodeType::Sequence:
         std::vector<Decay> result;
         for(auto && decay_str: node){
           result.emplace_back(get_decay(decay_str));
         }
         return result;
       }
       throw std::logic_error{"unreachable"};
     }
 
     ParticlesDecayMap get_all_decays(YAML::Node const & node,
                                            std::string const & entry
     ){
       if(!node[entry]) return {};
       if(!node[entry].IsMap())
         throw HEJ::invalid_type{entry + " have to be a map"};
       ParticlesDecayMap result;
       for(auto const & sub_node: node[entry]) {
         const auto name = sub_node.first.as<std::string>();
         const auto id = HEJ::to_ParticleID(name);
         result.emplace(id, get_decays(sub_node.second));
       }
       return result;
     }
 
     HEJ::ParticleProperties get_particle_properties(
         YAML::Node const & node, std::string const & entry,
         std::string const & boson
     ){
       HEJ::ParticleProperties result;
       set_from_yaml(result.mass, node, entry, boson, "mass");
       set_from_yaml(result.width, node, entry, boson, "width");
       return result;
     }
 
     HEJ::EWConstants get_ew_parameters(YAML::Node const & node){
       HEJ::EWConstants result;
       double vev;
       set_from_yaml(vev, node, "vev");
       result.set_vevWZH(vev,
         get_particle_properties(node, "particle properties", "W"),
         get_particle_properties(node, "particle properties", "Z"),
         get_particle_properties(node, "particle properties", "Higgs")
       );
       return result;
     }
 
     UnweightSettings get_unweight(
         YAML::Node const & node, std::string const & entry
     ){
       UnweightSettings result;
       set_from_yaml(result.sample_size, node, entry, "sample size");
       if(result.sample_size <= 0){
         throw std::invalid_argument{
           "negative sample size " + std::to_string(result.sample_size)
         };
       }
       set_from_yaml(result.max_dev, node, entry, "max deviation");
       return result;
     }
 
     Config to_Config(YAML::Node const & yaml){
       try{
         HEJ::assert_all_options_known(yaml, get_supported_options());
       }
       catch(HEJ::unknown_option const & ex){
         throw HEJ::unknown_option{std::string{"Unknown option '"} + ex.what() + "'"};
       }
 
       Config config;
       config.process = get_process(yaml, "process");
       set_from_yaml(config.events, yaml, "events");
       config.jets = get_jet_parameters(yaml, "jets");
       config.beam = get_Beam(yaml, "beam");
       for(size_t i = 0; i < config.process.incoming.size(); ++i){
         const auto & in = config.process.incoming[i];
         using namespace HEJ::pid;
         if( (in == p || in == p_bar) && in != config.beam.particles[i]){
           throw std::invalid_argument{
             "Particle type of beam " + std::to_string(i+1) + " incompatible"
             + " with type of incoming particle " + std::to_string(i+1)
           };
         }
       }
       set_from_yaml(config.pdf_id, yaml, "pdf");
 
       set_from_yaml(config.subleading_fraction, yaml, "subleading fraction");
       if(config.subleading_fraction < 0 || config.subleading_fraction > 1){
         throw std::invalid_argument{
           "subleading fraction has to be between 0 and 1"
         };
       }
       if(config.subleading_fraction == 0)
         config.subleading_channels = Subleading::none;
       else
         config.subleading_channels = get_subleading_channels(yaml["subleading channels"]);
 
       config.ew_parameters = get_ew_parameters(yaml);
-      config.particles_decays = get_all_decays(yaml, "decays");
+      config.particle_decays = get_all_decays(yaml, "decays");
       set_from_yaml_if_defined(config.analysis_parameters, yaml, "analysis");
       config.scales = HEJ::to_ScaleConfig(yaml);
       set_from_yaml_if_defined(config.output, yaml, "event output");
       config.rng = HEJ::to_RNGConfig(yaml, "random generator");
       config.Higgs_coupling = HEJ::get_Higgs_coupling(yaml, "Higgs coupling");
       if(yaml["unweight"]) config.unweight = get_unweight(yaml, "unweight");
       return config;
     }
 
   } // namespace anonymous
 
   Config load_config(std::string const & config_file){
     try{
       return to_Config(YAML::LoadFile(config_file));
     }
     catch(...){
       std::cerr << "Error reading " << config_file << ":\n  ";
       throw;
     }
   }
 }
diff --git a/FixedOrderGen/src/main.cc b/FixedOrderGen/src/main.cc
index f1fdbe9..d0b83a3 100644
--- a/FixedOrderGen/src/main.cc
+++ b/FixedOrderGen/src/main.cc
@@ -1,234 +1,234 @@
 /**
  *  \authors   The HEJ collaboration (see AUTHORS for details)
  *  \date      2019
  *  \copyright GPLv2 or later
  */
 #include <algorithm>
 #include <chrono>
 #include <fstream>
 #include <iostream>
 #include <map>
 #include <memory>
 
 #include "yaml-cpp/yaml.h"
 
 #include "LHEF/LHEF.h"
 
 #include "HEJ/CombinedEventWriter.hh"
 #include "HEJ/CrossSectionAccumulator.hh"
 #include "HEJ/get_analysis.hh"
 #include "HEJ/LesHouchesWriter.hh"
 #include "HEJ/make_RNG.hh"
 #include "HEJ/ProgressBar.hh"
 #include "HEJ/stream.hh"
 
 #include "config.hh"
 #include "EventGenerator.hh"
 #include "PhaseSpacePoint.hh"
 #include "Unweighter.hh"
 #include "Version.hh"
 
 namespace{
   constexpr auto banner =
     "     __  ___       __       ______                                   __   "
     " __                               \n    / / / (_)___ _/ /_     / ____/___ "
     " ___  _________ ___  __       / /__  / /______                         \n "
     "  / /_/ / / __ `/ __ \\   / __/ / __ \\/ _ \\/ ___/ __ `/ / / /  __  / / _"
     " \\/ __/ ___/                         \n  / __  / / /_/ / / / /  / /___/ /"
     " / /  __/ /  / /_/ / /_/ /  / /_/ /  __/ /_(__  )                         "
     " \n /_/ /_/_/\\__, /_/ /_/  /_____/_/ /_/\\___/_/   \\__, /\\__, /   \\___"
     "_/\\___/\\__/____/                           \n     ____///__/            "
     "__   ____          ///__//____/    ______                           __    "
     "        \n    / ____(_)  _____  ____/ /  / __ \\_________/ /__  _____   / "
     "____/__  ____  ___  _________ _/ /_____  _____\n   / /_  / / |/_/ _ \\/ __"
     "  /  / / / / ___/ __  / _ \\/ ___/  / / __/ _ \\/ __ \\/ _ \\/ ___/ __ `/ "
     "__/ __ \\/ ___/\n  / __/ / />  </  __/ /_/ /  / /_/ / /  / /_/ /  __/ /   "
     "  / /_/ /  __/ / / /  __/ /  / /_/ / /_/ /_/ / /    \n /_/   /_/_/|_|\\___"
     "/\\__,_/   \\____/_/   \\__,_/\\___/_/      \\____/\\___/_/ /_/\\___/_/   "
     "\\__,_/\\__/\\____/_/     \n";
 
   constexpr double invGeV2_to_pb = 389379292.;
   constexpr long long max_warmup_events = 10000;
 }
 
 HEJFOG::Config load_config(char const * filename){
   try{
     return HEJFOG::load_config(filename);
   }
   catch(std::exception const & exc){
     std::cerr << "Error: " << exc.what() << '\n';
     std::exit(EXIT_FAILURE);
   }
 }
 
 std::unique_ptr<HEJ::Analysis> get_analysis(
     YAML::Node const & parameters
 ){
   try{
     return HEJ::get_analysis(parameters);
   }
   catch(std::exception const & exc){
     std::cerr << "Failed to load analysis: " << exc.what() << '\n';
     std::exit(EXIT_FAILURE);
   }
 }
 
 int main(int argn, char** argv) {
   using namespace std::string_literals;
   if (argn < 2) {
     std::cerr << "\n# Usage:\n." << argv[0] << " config_file\n";
     return EXIT_FAILURE;
   }
   std::cout << banner;
   std::cout << "Version " << HEJFOG::Version::String()
              << ", revision " << HEJFOG::Version::revision() << std::endl;
   fastjet::ClusterSequence::print_banner();
   using clock = std::chrono::system_clock;
 
   const auto start_time = clock::now();
 
   // read configuration
   auto config = load_config(argv[1]);
 
   std::unique_ptr<HEJ::Analysis> analysis = get_analysis(
       config.analysis_parameters
   );
   assert(analysis != nullptr);
 
   auto ran = HEJ::make_RNG(config.rng.name, config.rng.seed);
   assert(ran != nullptr);
 
   HEJ::ScaleGenerator scale_gen{
     config.scales.base,
     config.scales.factors,
     config.scales.max_ratio
   };
 
   HEJFOG::EventGenerator generator{
     config.process,
     config.beam,
     std::move(scale_gen),
     config.jets,
     config.pdf_id,
     config.subleading_fraction,
     config.subleading_channels,
-    config.particles_decays,
+    config.particle_decays,
     config.Higgs_coupling,
     config.ew_parameters,
     *ran
   };
 
   LHEF::HEPRUP heprup;
   heprup.IDBMUP=std::pair<long,long>(config.beam.particles[0], config.beam.particles[1]);
   heprup.EBMUP=std::make_pair(config.beam.energy, config.beam.energy);
   heprup.PDFGUP=std::make_pair(0,0);
   heprup.PDFSUP=std::make_pair(config.pdf_id,config.pdf_id);
   heprup.NPRUP=1;
   heprup.XSECUP=std::vector<double>(1.);
   heprup.XERRUP=std::vector<double>(1.);
   heprup.LPRUP=std::vector<int>{1};
   heprup.generators.emplace_back(LHEF::XMLTag{});
   heprup.generators.back().name = HEJFOG::Version::package_name();
   heprup.generators.back().version = HEJFOG::Version::String();
 
   HEJ::CombinedEventWriter writer{config.output, heprup};
 
   HEJ::optional<HEJFOG::Unweighter> unweighter{};
   std::map<HEJFOG::Status, int> status_counter;
 
   std::vector<HEJ::Event> events;
   int trials = 0;
   // warm-up phase to train unweighter
   if(config.unweight) {
     std::cout << "Calibrating unweighting ...\n";
     const auto warmup_start = clock::now();
     const size_t warmup_events = config.unweight->sample_size;
     HEJ::ProgressBar<size_t> warmup_progress{std::cout, warmup_events};
     for(; events.size() < warmup_events; ++trials){
       auto ev = generator.gen_event();
       ++status_counter[generator.status()];
       assert( (generator.status() == HEJFOG::good) == bool(ev) );
       if(generator.status() == HEJFOG::good && analysis->pass_cuts(*ev, *ev)) {
         events.emplace_back(std::move(*ev));
         ++warmup_progress;
       }
     }
     std::cout << std::endl;
     unweighter = HEJFOG::Unweighter{
       begin(events), end(events), config.unweight->max_dev, *ran,
       config.jets.peak_pt?(*config.jets.peak_pt):0.
     };
     std::vector<HEJ::Event> unweighted_events;
     for(auto && ev: events) {
       auto unweighted = unweighter->unweight(std::move(ev));
       if(unweighted) {
         unweighted_events.emplace_back(std::move(*unweighted));
       }
     }
     events = std::move(unweighted_events);
     if(events.empty()) {
       std::cerr <<
         "Failed to generate events. Please increase \"unweight: sample size\""
         " or reduce \"unweight: max deviation\"\n";
       return EXIT_FAILURE;
     }
     const auto warmup_end = clock::now();
     const double completion = static_cast<double>(events.size())/config.events;
     const std::chrono::duration<double> remaining_time =
       (warmup_end- warmup_start)*(1./completion - 1);
     const auto finish = clock::to_time_t(
         std::chrono::time_point_cast<std::chrono::seconds>(warmup_end + remaining_time)
     );
     std::cout
       << "Generated " << events.size() << "/" << config.events << " events ("
       << static_cast<int>(std::round(100*completion)) << "%)\n"
       << "Estimated remaining generation time: "
       << remaining_time.count() << " seconds ("
       << std::put_time(std::localtime(&finish), "%c") << ")\n\n";
   }
 
   HEJ::ProgressBar<long long> progress{std::cout, config.events};
   progress.increment(events.size());
   events.reserve(config.events);
   for(; events.size() < static_cast<size_t>(config.events); ++trials){
     auto ev = generator.gen_event();
     ++status_counter[generator.status()];
     assert( (generator.status() == HEJFOG::good) == bool(ev) );
     if(generator.status() == HEJFOG::good && analysis->pass_cuts(*ev, *ev)) {
       if(unweighter) {
         auto unweighted = unweighter->unweight(std::move(*ev));
         if(! unweighted) continue;
         ev = std::move(unweighted);
       }
       events.emplace_back(std::move(*ev));
       ++progress;
     }
   }
   std::cout << std::endl;
 
   HEJ::CrossSectionAccumulator xs;
   for(auto & ev: events){
     ev.parameters() *= invGeV2_to_pb/trials;
     analysis->fill(ev, ev);
     writer.write(ev);
     xs.fill(ev);
   }
   analysis->finalise();
 
   const std::chrono::duration<double> run_time = (clock::now() - start_time);
   std::cout << "\nTask Runtime: " << run_time.count() << " seconds.\n\n";
 
   std::cout << xs << '\n';
 
   for(auto && entry: status_counter){
     const double fraction = static_cast<double>(entry.second)/trials;
     const int percent = std::round(100*fraction);
     std::cout << "status "
               << std::left << std::setw(16) << (to_string(entry.first) + ":")
               << " [";
     for(int i = 0; i < percent/2; ++i) std::cout << '#';
     for(int i = percent/2; i < 50; ++i) std::cout << ' ';
     std::cout << "] " << percent << "%\n";
   }
   return EXIT_SUCCESS;
 }
diff --git a/FixedOrderGen/t/2j.cc b/FixedOrderGen/t/2j.cc
index 99419ba..7d0ebd6 100644
--- a/FixedOrderGen/t/2j.cc
+++ b/FixedOrderGen/t/2j.cc
@@ -1,67 +1,67 @@
 /**
  *  \authors   The HEJ collaboration (see AUTHORS for details)
  *  \date      2019
  *  \copyright GPLv2 or later
  */
 #ifdef NDEBUG
 #undef NDEBUG
 #endif
 
 #include <algorithm>
 #include <cmath>
 #include <cassert>
 #include <iostream>
 
 #include "config.hh"
 #include "EventGenerator.hh"
 #include "HEJ/Mixmax.hh"
 
 #include "HEJ/Event.hh"
 #include "HEJ/PDF.hh"
 #include "HEJ/MatrixElement.hh"
 
 using namespace HEJFOG;
 
 int main(){
   constexpr double invGeV2_to_pb = 389379292.;
   constexpr double xs_ref = 86.42031848*1e6; //calculated with "combined" HEJ svn r3480
 
   auto config = load_config("config_2j.yml");
 
   HEJ::Mixmax ran{};
   HEJFOG::EventGenerator generator{
     config.process,
     config.beam,
     HEJ::ScaleGenerator{
       config.scales.base,
       config.scales.factors,
       config.scales.max_ratio
     },
     config.jets,
     config.pdf_id,
     config.subleading_fraction,
     config.subleading_channels,
-    config.particles_decays,
+    config.particle_decays,
     config.Higgs_coupling,
     config.ew_parameters,
     ran
   };
 
   double xs = 0., xs_err = 0.;
   for (int trials = 0; trials < config.events; ++trials){
     auto ev = generator.gen_event();
     if(generator.status() != good) continue;
     assert(ev);
     ev->central().weight *= invGeV2_to_pb;
     ev->central().weight /= config.events;
 
     xs += ev->central().weight;
     xs_err += ev->central().weight*ev->central().weight;
   }
   xs_err = std::sqrt(xs_err);
   std::cout << xs_ref << " ~ " << xs << " +- " << xs_err << '\n';
 
   assert(std::abs(xs - xs_ref) < 3*xs_err);
   assert(xs_err < 0.01*xs);
   return EXIT_SUCCESS;
 }
diff --git a/FixedOrderGen/t/4j.cc b/FixedOrderGen/t/4j.cc
index 8d9aa41..b9fdef1 100644
--- a/FixedOrderGen/t/4j.cc
+++ b/FixedOrderGen/t/4j.cc
@@ -1,68 +1,68 @@
 /**
  *  \authors   The HEJ collaboration (see AUTHORS for details)
  *  \date      2019
  *  \copyright GPLv2 or later
  */
 #ifdef NDEBUG
 #undef NDEBUG
 #endif
 
 #include <algorithm>
 #include <cmath>
 #include <cassert>
 #include <iostream>
 
 #include "config.hh"
 #include "EventGenerator.hh"
 #include "HEJ/Mixmax.hh"
 
 #include "HEJ/Event.hh"
 #include "HEJ/PDF.hh"
 #include "HEJ/MatrixElement.hh"
 
 using namespace HEJFOG;
 
 int main(){
   constexpr double invGeV2_to_pb = 389379292.;
   constexpr double xs_ref = 0.81063619*1e6; //calculated with "combined" HEJ svn r3480
 
   auto config = load_config("config_2j.yml");
   config.process.njets = 4;
 
   HEJ::Mixmax ran{};
   HEJFOG::EventGenerator generator{
     config.process,
     config.beam,
     HEJ::ScaleGenerator{
       config.scales.base,
       config.scales.factors,
       config.scales.max_ratio
     },
     config.jets,
     config.pdf_id,
     config.subleading_fraction,
     config.subleading_channels,
-    config.particles_decays,
+    config.particle_decays,
     config.Higgs_coupling,
     config.ew_parameters,
     ran
   };
 
   double xs = 0., xs_err = 0.;
   for (int trials = 0; trials < config.events; ++trials){
     auto ev = generator.gen_event();
     if(generator.status() != good) continue;
     assert(ev);
     ev->central().weight *= invGeV2_to_pb;
     ev->central().weight /= config.events;
 
     xs += ev->central().weight;
     xs_err += ev->central().weight*ev->central().weight;
   }
   xs_err = std::sqrt(xs_err);
   std::cout << xs_ref << " ~ " << xs << " +- " << xs_err << '\n';
 
   assert(std::abs(xs - xs_ref) < 3*xs_err);
   assert(xs_err < 0.03*xs);
   return EXIT_SUCCESS;
 }
diff --git a/FixedOrderGen/t/W_reconstruct_enu.cc b/FixedOrderGen/t/W_reconstruct_enu.cc
index 8af3615..badb36a 100644
--- a/FixedOrderGen/t/W_reconstruct_enu.cc
+++ b/FixedOrderGen/t/W_reconstruct_enu.cc
@@ -1,72 +1,72 @@
 /**
  *  \brief     that the reconstruction of the W works
  *
  *  \authors   The HEJ collaboration (see AUTHORS for details)
  *  \date      2019
  *  \copyright GPLv2 or later
  */
 #ifdef NDEBUG
 #undef NDEBUG
 #endif
 
 #include <algorithm>
 
 #include "config.hh"
 #include "EventGenerator.hh"
 
 #include "HEJ/Event.hh"
 #include "HEJ/Mixmax.hh"
 
 using namespace HEJFOG;
 using namespace HEJ;
 namespace {
   constexpr size_t num_events = 1000;
   constexpr double invGeV2_to_pb = 389379292.;
 }
 
 double get_xs(std::string config_name){
   auto config { load_config(config_name) };
   config.events = num_events;
   HEJ::Mixmax ran{1};
   HEJFOG::EventGenerator generator{
     config.process,
     config.beam,
     HEJ::ScaleGenerator{
       config.scales.base,
       config.scales.factors,
       config.scales.max_ratio
     },
     config.jets,
     config.pdf_id,
     config.subleading_fraction,
     config.subleading_channels,
-    config.particles_decays,
+    config.particle_decays,
     config.Higgs_coupling,
     config.ew_parameters,
     ran
   };
 
   double xs = 0.;
   for (int trials = 0; trials < config.events; ++trials){
     auto ev = generator.gen_event();
     if(generator.status() != good) continue;
     assert(ev);
     ev->central().weight *= invGeV2_to_pb;
     ev->central().weight /= config.events;
     xs += ev->central().weight;
   }
   return xs;
 }
 
 int main(){
 
   double xs_W{   get_xs("config_Wp_2j.yml")};
   double xs_enu{ get_xs("config_Wp_2j_decay.yml")};
   if(std::abs(xs_W/xs_enu-1.)>1e-6){
     std::cerr << "Reconstructing the W in the runcard gave a different results ("
       << xs_W << " vs. "<< xs_enu << " -> " << std::abs(xs_W/xs_enu-1.)*100 << "%)\n";
     return EXIT_FAILURE;
   }
 
   return EXIT_SUCCESS;
 }
diff --git a/FixedOrderGen/t/h_2j.cc b/FixedOrderGen/t/h_2j.cc
index 18c11d0..e993a8d 100644
--- a/FixedOrderGen/t/h_2j.cc
+++ b/FixedOrderGen/t/h_2j.cc
@@ -1,75 +1,75 @@
 /**
  *  \authors   The HEJ collaboration (see AUTHORS for details)
  *  \date      2019
  *  \copyright GPLv2 or later
  */
 #ifdef NDEBUG
 #undef NDEBUG
 #endif
 
 #include <algorithm>
 #include <cmath>
 #include <cassert>
 #include <iostream>
 
 #include "config.hh"
 #include "EventGenerator.hh"
 #include "HEJ/Mixmax.hh"
 
 #include "HEJ/Event.hh"
 #include "HEJ/PDF.hh"
 #include "HEJ/MatrixElement.hh"
 
 using namespace HEJFOG;
 
 int main(){
   constexpr double invGeV2_to_pb = 389379292.;
   constexpr double xs_ref = 2.04928; // +- 0.00377252
   //calculated with HEJ revision 9570e3809613272ac4b8bf3236279ba23cf64d20
 
   auto config = load_config("config_h_2j.yml");
 
   HEJ::Mixmax ran{};
   HEJFOG::EventGenerator generator{
     config.process,
     config.beam,
     HEJ::ScaleGenerator{
       config.scales.base,
       config.scales.factors,
       config.scales.max_ratio
     },
     config.jets,
     config.pdf_id,
     config.subleading_fraction,
     config.subleading_channels,
-    config.particles_decays,
+    config.particle_decays,
     config.Higgs_coupling,
     config.ew_parameters,
     ran
   };
 
   double xs = 0., xs_err = 0.;
   for (int trials = 0; trials < config.events; ++trials){
     auto ev = generator.gen_event();
     if(generator.status() != good) continue;
     assert(ev);
     ev->central().weight *= invGeV2_to_pb;
     ev->central().weight /= config.events;
 
     const auto the_Higgs = std::find_if(
         begin(ev->outgoing()), end(ev->outgoing()),
         [](HEJ::Particle const & p){ return p.type == HEJ::ParticleID::h; }
     );
     assert(the_Higgs != end(ev->outgoing()));
     if(std::abs(the_Higgs->rapidity()) > 5.) continue;
 
     xs += ev->central().weight;
     xs_err += ev->central().weight*ev->central().weight;
   }
   xs_err = std::sqrt(xs_err);
   std::cout << xs_ref << " ~ " << xs << " +- " << xs_err << std::endl;
 
   assert(std::abs(xs - xs_ref) < 3*xs_err);
   assert(xs_err < 0.01*xs);
   return EXIT_SUCCESS;
 }
diff --git a/FixedOrderGen/t/h_2j_decay.cc b/FixedOrderGen/t/h_2j_decay.cc
index 8774f18..0d25f19 100644
--- a/FixedOrderGen/t/h_2j_decay.cc
+++ b/FixedOrderGen/t/h_2j_decay.cc
@@ -1,94 +1,94 @@
 /**
  *  \authors   The HEJ collaboration (see AUTHORS for details)
  *  \date      2019
  *  \copyright GPLv2 or later
  */
 #ifdef NDEBUG
 #undef NDEBUG
 #endif
 
 #include <algorithm>
 #include <cmath>
 #include <cassert>
 #include <iostream>
 
 #include "config.hh"
 #include "EventGenerator.hh"
 
 #include "HEJ/Event.hh"
 #include "HEJ/MatrixElement.hh"
 #include "HEJ/Particle.hh"
 #include "HEJ/PDF.hh"
 #include "HEJ/Ranlux64.hh"
 #include "HEJ/utility.hh"
 
 using namespace HEJFOG;
 
 bool pass_dR_cut(
     std::vector<fastjet::PseudoJet> const & jets,
     std::vector<HEJ::Particle> const & photons
 ){
   constexpr double delta_R_min = 0.7;
   for(auto const & jet: jets){
     for(auto const & photon: photons){
       if(jet.delta_R(photon.p) < delta_R_min) return false;
     }
   }
   return true;
 }
 
 int main(){
   constexpr double invGeV2_to_pb = 389379292.;
   constexpr double xs_ref = 0.00429198; // +- 1.0488e-05
   //calculated with HEJ revision 9570e3809613272ac4b8bf3236279ba23cf64d20
 
   auto config = load_config("config_h_2j_decay.yml");
 
   HEJ::Ranlux64 ran{};
   HEJFOG::EventGenerator generator{
     config.process,
     config.beam,
     HEJ::ScaleGenerator{
       config.scales.base,
       config.scales.factors,
       config.scales.max_ratio
     },
     config.jets,
     config.pdf_id,
     config.subleading_fraction,
     config.subleading_channels,
-    config.particles_decays,
+    config.particle_decays,
     config.Higgs_coupling,
     config.ew_parameters,
     ran
   };
 
   double xs = 0., xs_err = 0.;
   for (int trials = 0; trials < config.events; ++trials){
     auto ev = generator.gen_event();
     if(generator.status() != good) continue;
     assert(ev);
     assert(ev->decays().size() == 1);
     const auto decay = begin(ev->decays());
     assert(ev->outgoing().size() > decay->first);
     const auto & the_Higgs = ev->outgoing()[decay->first];
     assert(the_Higgs.type == HEJ::pid::Higgs);
     assert(decay->second.size() == 2);
     auto const & gamma = decay->second;
     assert(gamma[0].type == HEJ::pid::photon);
     assert(gamma[1].type == HEJ::pid::photon);
     assert(HEJ::nearby_ep(gamma[0].p + gamma[1].p, the_Higgs.p, 1e-6));
     if(!pass_dR_cut(ev->jets(), gamma)) continue;
     ev->central().weight *= invGeV2_to_pb;
     ev->central().weight /= config.events;
 
     xs += ev->central().weight;
     xs_err += ev->central().weight*ev->central().weight;
   }
   xs_err = std::sqrt(xs_err);
   std::cout << xs_ref << " ~ " << xs << " +- " << xs_err << std::endl;
 
   assert(std::abs(xs - xs_ref) < 3*xs_err);
   assert(xs_err < 0.012*xs);
   return EXIT_SUCCESS;
 }
diff --git a/FixedOrderGen/t/h_3j.cc b/FixedOrderGen/t/h_3j.cc
index c4a9e8a..8d134ca 100644
--- a/FixedOrderGen/t/h_3j.cc
+++ b/FixedOrderGen/t/h_3j.cc
@@ -1,76 +1,76 @@
 /**
  *  \authors   The HEJ collaboration (see AUTHORS for details)
  *  \date      2019
  *  \copyright GPLv2 or later
  */
 #ifdef NDEBUG
 #undef NDEBUG
 #endif
 
 #include <algorithm>
 #include <cmath>
 #include <cassert>
 #include <iostream>
 
 #include "config.hh"
 #include "EventGenerator.hh"
 #include "HEJ/Ranlux64.hh"
 
 #include "HEJ/Event.hh"
 #include "HEJ/MatrixElement.hh"
 #include "HEJ/PDF.hh"
 
 using namespace HEJFOG;
 
 int main(){
   constexpr double invGeV2_to_pb = 389379292.;
   constexpr double xs_ref = 1.07807; // +- 0.0071
   //calculated with HEJ revision 93efdc851b02a907a6fcc63956387f9f4c1111c2 +1
 
   auto config = load_config("config_h_2j.yml");
   config.process.njets = 3;
 
   HEJ::Ranlux64 ran{};
   HEJFOG::EventGenerator generator{
     config.process,
     config.beam,
     HEJ::ScaleGenerator{
       config.scales.base,
       config.scales.factors,
       config.scales.max_ratio
     },
     config.jets,
     config.pdf_id,
     config.subleading_fraction,
     config.subleading_channels,
-    config.particles_decays,
+    config.particle_decays,
     config.Higgs_coupling,
     config.ew_parameters,
     ran
   };
 
   double xs = 0., xs_err = 0.;
   for (int trials = 0; trials < config.events; ++trials){
     auto ev = generator.gen_event();
     if(generator.status() != good) continue;
     assert(ev);
     ev->central().weight *= invGeV2_to_pb;
     ev->central().weight /= config.events;
 
     const auto the_Higgs = std::find_if(
         begin(ev->outgoing()), end(ev->outgoing()),
         [](HEJ::Particle const & p){ return p.type == HEJ::ParticleID::h; }
     );
     assert(the_Higgs != end(ev->outgoing()));
     if(std::abs(the_Higgs->rapidity()) > 5.) continue;
 
     xs += ev->central().weight;
     xs_err += ev->central().weight*ev->central().weight;
   }
   xs_err = std::sqrt(xs_err);
   std::cout << xs_ref << " ~ " << xs << " +- " << xs_err << std::endl;
 
   assert(std::abs(xs - xs_ref) < 3*xs_err);
   assert(xs_err < 0.02*xs);
   return EXIT_SUCCESS;
 }
diff --git a/FixedOrderGen/t/h_3j_uno1.cc b/FixedOrderGen/t/h_3j_uno1.cc
index 0befb62..94bc80e 100644
--- a/FixedOrderGen/t/h_3j_uno1.cc
+++ b/FixedOrderGen/t/h_3j_uno1.cc
@@ -1,80 +1,80 @@
 /**
  *  check that adding uno emissions doesn't change the FKL cross section
  *
  *  \authors   The HEJ collaboration (see AUTHORS for details)
  *  \date      2019
  *  \copyright GPLv2 or later
  */
 #ifdef NDEBUG
 #undef NDEBUG
 #endif
 
 #include <algorithm>
 #include <cassert>
 #include <cmath>
 #include <iostream>
 
 #include "config.hh"
 #include "EventGenerator.hh"
 #include "HEJ/Ranlux64.hh"
 #include "Subleading.hh"
 
 #include "HEJ/Event.hh"
 #include "HEJ/MatrixElement.hh"
 #include "HEJ/PDF.hh"
 
 using namespace HEJFOG;
 
 int main(){
   constexpr double invGeV2_to_pb = 389379292.;
   constexpr double xs_ref = 0.0243548; // +- 0.000119862
   //calculated with HEJ revision 9570e3809613272ac4b8bf3236279ba23cf64d20
 
   auto config = load_config("config_h_2j.yml");
   config.process.njets = 3;
   config.process.incoming = {HEJ::pid::u, HEJ::pid::u};
   config.subleading_channels = HEJFOG::Subleading::uno;
 
   HEJ::Ranlux64 ran{};
   HEJFOG::EventGenerator generator{
     config.process,
     config.beam,
     HEJ::ScaleGenerator{
       config.scales.base,
       config.scales.factors,
       config.scales.max_ratio
     },
     config.jets,
     config.pdf_id,
     config.subleading_fraction,
     config.subleading_channels,
-    config.particles_decays,
+    config.particle_decays,
     config.Higgs_coupling,
     config.ew_parameters,
     ran
   };
 
   double xs = 0., xs_err = 0.;
   int uno_found = 0;
   for (int trials = 0; trials < config.events; ++trials){
     auto ev = generator.gen_event();
     if(generator.status() != good) continue;
     assert(ev);
     if(ev->type() != HEJ::event_type::FKL){
       ++uno_found;
       continue;
     }
     ev->central().weight *= invGeV2_to_pb;
     ev->central().weight /= config.events;
 
     xs += ev->central().weight;
     xs_err += ev->central().weight*ev->central().weight;
   }
   xs_err = std::sqrt(xs_err);
   std::cout << xs_ref << " ~ " << xs << " +- " << xs_err << '\n';
   std::cout << uno_found << " events with unordered emission" << std::endl;
   assert(uno_found > 0);
   assert(std::abs(xs - xs_ref) < 3*xs_err);
   assert(xs_err < 0.05*xs);
   return EXIT_SUCCESS;
 }
diff --git a/FixedOrderGen/t/h_3j_uno2.cc b/FixedOrderGen/t/h_3j_uno2.cc
index 3cb4ae7..ab069d9 100644
--- a/FixedOrderGen/t/h_3j_uno2.cc
+++ b/FixedOrderGen/t/h_3j_uno2.cc
@@ -1,75 +1,75 @@
 /**
  * check uno cross section
  *
  *  \authors   The HEJ collaboration (see AUTHORS for details)
  *  \date      2019
  *  \copyright GPLv2 or later
  */
 #ifdef NDEBUG
 #undef NDEBUG
 #endif
 
 #include <algorithm>
 #include <cassert>
 #include <cmath>
 #include <iostream>
 
 #include "config.hh"
 #include "EventGenerator.hh"
 #include "HEJ/Ranlux64.hh"
 #include "Subleading.hh"
 
 #include "HEJ/Event.hh"
 #include "HEJ/MatrixElement.hh"
 #include "HEJ/PDF.hh"
 
 using namespace HEJFOG;
 
 int main(){
   constexpr double invGeV2_to_pb = 389379292.;
   constexpr double xs_ref = 0.00347538; // +- 3.85875e-05
   //calculated with HEJ revision 9570e3809613272ac4b8bf3236279ba23cf64d20
 
   auto config = load_config("config_h_2j.yml");
   config.process.njets = 3;
   config.process.incoming = {HEJ::pid::u, HEJ::pid::u};
   config.subleading_fraction = 1.;
   config.subleading_channels = HEJFOG::Subleading::uno;
 
   HEJ::Ranlux64 ran{};
   HEJFOG::EventGenerator generator{
     config.process,
     config.beam,
     HEJ::ScaleGenerator{
       config.scales.base,
       config.scales.factors,
       config.scales.max_ratio
     },
     config.jets,
     config.pdf_id,
     config.subleading_fraction,
     config.subleading_channels,
-    config.particles_decays,
+    config.particle_decays,
     config.Higgs_coupling,
     config.ew_parameters,
     ran
   };
 
   double xs = 0., xs_err = 0.;
   for (int trials = 0; trials < config.events; ++trials){
     auto ev = generator.gen_event();
     if(generator.status() != good) continue;
     assert(ev);
     if(ev->type() == HEJ::event_type::FKL) continue;
     ev->central().weight *= invGeV2_to_pb;
     ev->central().weight /= config.events;
 
     xs += ev->central().weight;
     xs_err += ev->central().weight*ev->central().weight;
   }
   xs_err = std::sqrt(xs_err);
   std::cout << xs_ref << " ~ " << xs << " +- " << xs_err << std::endl;
   assert(std::abs(xs - xs_ref) < 3*xs_err);
   assert(xs_err < 0.05*xs);
   return EXIT_SUCCESS;
 }
diff --git a/FixedOrderGen/t/h_5j.cc b/FixedOrderGen/t/h_5j.cc
index d6d3ffa..cbcd7a2 100644
--- a/FixedOrderGen/t/h_5j.cc
+++ b/FixedOrderGen/t/h_5j.cc
@@ -1,72 +1,72 @@
 /**
  *  This is a regression test
  *  the reference cross section has not been checked against any other program
  *
  *  \authors   The HEJ collaboration (see AUTHORS for details)
  *  \date      2019
  *  \copyright GPLv2 or later
  */
 #ifdef NDEBUG
 #undef NDEBUG
 #endif
 
 #include <algorithm>
 #include <cassert>
 #include <cmath>
 #include <iostream>
 
 #include "config.hh"
 #include "EventGenerator.hh"
 #include "HEJ/Ranlux64.hh"
 
 #include "HEJ/Event.hh"
 #include "HEJ/MatrixElement.hh"
 #include "HEJ/PDF.hh"
 
 using namespace HEJFOG;
 
 int main(){
   constexpr double invGeV2_to_pb = 389379292.;
   constexpr double xs_ref = 0.252273; // +- 0.00657742
   //calculated with HEJ revision 9570e3809613272ac4b8bf3236279ba23cf64d20
 
   auto config = load_config("config_h_2j.yml");
   config.process.njets = 5;
 
   HEJ::Ranlux64 ran{};
   HEJFOG::EventGenerator generator{
     config.process,
     config.beam,
     HEJ::ScaleGenerator{
       config.scales.base,
       config.scales.factors,
       config.scales.max_ratio
     },
     config.jets,
     config.pdf_id,
     config.subleading_fraction,
     config.subleading_channels,
-    config.particles_decays,
+    config.particle_decays,
     config.Higgs_coupling,
     config.ew_parameters,
     ran
   };
 
   double xs = 0., xs_err = 0.;
   for (int trials = 0; trials < config.events; ++trials){
     auto ev = generator.gen_event();
     if(generator.status() != good) continue;
     assert(ev);
     ev->central().weight *= invGeV2_to_pb;
     ev->central().weight /= config.events;
 
     xs += ev->central().weight;
     xs_err += ev->central().weight*ev->central().weight;
   }
   xs_err = std::sqrt(xs_err);
   std::cout << xs_ref << " ~ " << xs << " +- " << xs_err << std::endl;
 
   assert(std::abs(xs - xs_ref) < 3*xs_err);
   assert(xs_err < 0.06*xs);
   return EXIT_SUCCESS;
 }