diff --git a/src/YAMLreader.cc b/src/YAMLreader.cc
index 584c58f..798092d 100644
--- a/src/YAMLreader.cc
+++ b/src/YAMLreader.cc
@@ -1,431 +1,427 @@
 #include "RHEJ/YAMLreader.hh"
 
 #include <set>
 #include <string>
 #include <vector>
 #include <iostream>
 #include <stdexcept>
 
 namespace RHEJ{
 
   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 = {
           "trials", "min extparton pt", "max ext soft pt fraction",
           "FKL", "unordered", "non-FKL",
           "scales", "scale factors", "max scale ratio",
           "log correction", "unweight", "event output", "analysis",
           "RanLux init"
         };
         // add subnodes to "supported" - the assigned value is irrelevant
         for(auto && opt: opts) supported[opt] = "";
         for(auto && jet_opt: {"min pt", "algorithm", "R"}){
           supported["resummation jets"][jet_opt] = "";
           supported["fixed order jets"][jet_opt] = "";
         }
         for(auto && opt: {"mt", "use impact factors", "include bottom", "mb"}){
           supported["Higgs coupling"][opt] = "";
         }
         return supported;
       }();
       return supported;
     }
 
     fastjet::JetAlgorithm to_JetAlgorithm(std::string const & algo){
       using namespace fastjet;
       static const std::map<std::string, fastjet::JetAlgorithm> known = {
         {"kt", kt_algorithm},
         {"cambridge", cambridge_algorithm},
         {"antikt", antikt_algorithm},
         {"genkt", genkt_algorithm},
         {"cambridge for passive", cambridge_for_passive_algorithm},
         {"genkt for passive", genkt_for_passive_algorithm},
         {"ee kt", ee_kt_algorithm},
         {"ee genkt", ee_genkt_algorithm},
         {"plugin", plugin_algorithm}
       };
       const auto res = known.find(algo);
       if(res == known.end()){
         throw std::invalid_argument("Unknown jet algorithm " + algo);
       }
       return res->second;
     }
 
     EventTreatment to_EventTreatment(std::string const & name){
       static const std::map<std::string, EventTreatment> known = {
         {"reweight", EventTreatment::reweight},
         {"keep", EventTreatment::keep},
         {"discard", EventTreatment::discard}
       };
       const auto res = known.find(name);
       if(res == known.end()){
         throw std::invalid_argument("Unknown event treatment " + name);
       }
       return res->second;
     }
 
   } // namespace anonymous
 
-  namespace detail{
-
-  } // namespace detail
-
   ParticleID to_ParticleID(std::string const & name){
     using namespace RHEJ::pid;
     static const std::map<std::string, ParticleID> known = {
       {"d", d}, {"down", down}, {"u", u}, {"up", up}, {"s", s}, {"strange", strange},
       {"c", c}, {"charm", charm}, {"b", b}, {"bottom", bottom}, {"t", t}, {"top", top},
       {"e", e}, {"electron", electron}, {"nu_e", nu_e}, {"electron_neutrino", electron_neutrino},
       {"mu", mu}, {"muon", muon}, {"nu_mu", nu_mu}, {"muon_neutrino", muon_neutrino},
       {"tau", tau}, {"nu_tau", nu_tau}, {"tau_neutrino", tau_neutrino},
       {"d_bar", d_bar}, {"u_bar", u_bar}, {"s_bar", s_bar}, {"c_bar", c_bar},
       {"b_bar", b_bar}, {"t_bar", t_bar}, {"e_bar", e_bar},
       {"nu_e_bar", nu_e_bar}, {"mu_bar", mu_bar}, {"nu_mu_bar", nu_mu_bar},
       {"tau_bar", tau_bar}, {"nu_tau_bar", nu_tau_bar},
       {"gluon", gluon}, {"g", g}, {"photon", photon}, {"gamma", gamma},
       {"Z", Z}, {"Wp", Wp}, {"Wm", Wm}, {"W+", Wp}, {"W-", Wm},
       {"h", h}, {"H", h}, {"Higgs", Higgs}, {"higgs", higgs},
       {"p", p}, {"proton", proton}, {"p_bar", p_bar}
     };
     const auto res = known.find(name);
     if(res == known.end()){
       throw std::invalid_argument("Unknown particle " + name);
     }
     return res->second;
   }
 
   namespace detail{
     void set_from_yaml(fastjet::JetAlgorithm & setting, YAML::Node const & yaml){
       setting = to_JetAlgorithm(yaml.as<std::string>());
     }
 
     void set_from_yaml(EventTreatment & setting, YAML::Node const & yaml){
       setting = to_EventTreatment(yaml.as<std::string>());
     }
 
     void set_from_yaml(ParticleID & setting, YAML::Node const & yaml){
       setting = to_ParticleID(yaml.as<std::string>());
     }
   } // namespace detail
 
   JetParameters get_jet_parameters(
       YAML::Node const & node,
       std::string const & entry
   ){
     assert(node);
     JetParameters result;
     fastjet::JetAlgorithm jet_algo = fastjet::antikt_algorithm;
     double R;
     set_from_yaml_if_defined(jet_algo, node, entry, "algorithm");
     set_from_yaml(R, node, entry, "R");
     result.def = fastjet::JetDefinition{jet_algo, R};
     set_from_yaml(result.min_pt, node, entry, "min pt");
     return result;
   }
 
   HiggsCouplingSettings get_Higgs_coupling(
       YAML::Node const & node,
       std::string const & entry
   ){
     assert(node);
     static constexpr double mt_max = 2e4;
 #ifndef RHEJ_BUILD_WITH_QCDLOOP
     if(node[entry]){
       throw std::invalid_argument{
         "Higgs coupling settings require building Reversed HEJ "
           "with QCDloop support"
           };
     }
 #endif
     HiggsCouplingSettings settings;
     set_from_yaml_if_defined(settings.mt, node, entry, "mt");
     set_from_yaml_if_defined(settings.mb, node, entry, "mb");
     set_from_yaml_if_defined(settings.include_bottom, node, entry, "include bottom");
     set_from_yaml_if_defined(settings.use_impact_factors, node, entry, "use impact factors");
     if(settings.use_impact_factors){
       if(settings.mt != std::numeric_limits<double>::infinity()){
         throw std::invalid_argument{
           "Conflicting settings: "
             "impact factors may only be used in the infinite top mass limit"
             };
       }
     }
     else{
       // huge values of the top mass are numerically unstable
       settings.mt = std::min(settings.mt, mt_max);
     }
     return settings;
   }
 
   FileFormat to_FileFormat(std::string const & name){
     static const std::map<std::string, FileFormat> known = {
       {"Les Houches", FileFormat::Les_Houches},
       {"HepMC", FileFormat::HepMC}
     };
     const auto res = known.find(name);
     if(res == known.end()){
       throw std::invalid_argument("Unknown file format " + name);
     }
     return res->second;
   }
 
   std::string extract_suffix(std::string const & filename){
     size_t separator = filename.rfind('.');
     if(separator == filename.npos) return {};
     return filename.substr(separator + 1);
   }
 
   FileFormat format_from_suffix(std::string const & filename){
     const std::string suffix = extract_suffix(filename);
     if(suffix == "lhe") return FileFormat::Les_Houches;
     if(suffix == "hepmc") return FileFormat::HepMC;
     throw std::invalid_argument{
       "Can't determine format for output file " + filename
     };
   }
 
   void assert_all_options_known(
       YAML::Node const & conf, YAML::Node const & supported
   ){
     if(!conf.IsMap()) return;
     if(!supported.IsMap()) throw invalid_type{"must not have sub-entries"};
     for(auto const & entry: conf){
       const auto name = entry.first.as<std::string>();
       if(! supported[name]) throw unknown_option{name};
       /* check sub-options, e.g. 'resummation jets: min pt'
        * we don't check analysis sub-options
        * those depend on the analysis being used and should be checked there
        */
       if(name != "analysis"){
         try{
           assert_all_options_known(conf[name], supported[name]);
         }
         catch(unknown_option const & ex){
           throw unknown_option{name + ": " + ex.what()};
         }
         catch(invalid_type const & ex){
           throw invalid_type{name + ": " + ex.what()};
         }
       }
     }
   }
 
 } // namespace RHEJ
 
 namespace YAML {
 
   Node convert<RHEJ::OutputFile>::encode(RHEJ::OutputFile const & outfile) {
     Node node;
     node[to_string(outfile.format)] = outfile.name;
     return node;
   };
 
   bool convert<RHEJ::OutputFile>::decode(Node const & node, RHEJ::OutputFile & out) {
     switch(node.Type()){
     case NodeType::Map: {
       YAML::const_iterator it = node.begin();
       out.format = RHEJ::to_FileFormat(it->first.as<std::string>());
       out.name = it->second.as<std::string>();
       return true;
     }
     case NodeType::Scalar:
       out.name = node.as<std::string>();
       out.format = RHEJ::format_from_suffix(out.name);
       return true;
     default:
       return false;
     }
   }
 } // namespace YAML
 
 namespace RHEJ{
 
   namespace detail{
     void set_from_yaml(OutputFile & setting, YAML::Node const & yaml){
       setting = yaml.as<OutputFile>();
     }
   }
 
   namespace{
     void update_fixed_order_jet_parameters(
         JetParameters & fixed_order_jets, YAML::Node const & yaml
     ){
       if(!yaml["fixed order jets"]) return;
       set_from_yaml_if_defined(
           fixed_order_jets.min_pt, yaml, "fixed order jets", "min pt"
       );
       fastjet::JetAlgorithm algo = fixed_order_jets.def.jet_algorithm();
       set_from_yaml_if_defined(algo, yaml, "fixed order jets", "algorithm");
       double R = fixed_order_jets.def.R();
       set_from_yaml_if_defined(R, yaml, "fixed order jets", "R");
       fixed_order_jets.def = fastjet::JetDefinition{algo, R};
     }
 
     // like std::stod, but throw if not the whole string can be converted
     double to_double(std::string const & str){
       std::size_t pos;
       const double result = std::stod(str, &pos);
       if(pos < str.size()){
         throw std::invalid_argument(str + " is not a valid double value");
       }
       return result;
     }
 
     // simple (as in non-composite) scale functions
     /**
      * An example for a simple scale function would be H_T,
      * H_T/2 is then composite (take H_T and then divide by 2)
      */
     ScaleFunction parse_simple_ScaleFunction(std::string const & scale_fun) {
       assert(
           scale_fun.empty() ||
           (!std::isspace(scale_fun.front()) && !std::isspace(scale_fun.back()))
       );
       if(scale_fun == "H_T") return H_T;
       if(scale_fun == "max jet pperp") return max_jet_pt;
       if(scale_fun == "jet invariant mass") return jet_invariant_mass;
       if(scale_fun == "m_j1j2") return m_j1j2;
       try{
         const double scale = to_double(scale_fun);
         return FixedScale{scale};
       } catch(std::invalid_argument const &){}
       throw std::invalid_argument{"Unknown scale choice: " + scale_fun};
     }
 
     std::string trim_front(std::string const & str){
       const auto new_begin = std::find_if(
           begin(str), end(str), [](char c){ return ! std::isspace(c); }
       );
       return std::string(new_begin, end(str));
     }
 
     std::string trim_back(std::string str){
       size_t pos = str.size() - 1;
       // use guaranteed wrap-around behaviour to check whether we have
       // traversed the whole string
       for(; pos < str.size() && std::isspace(str[pos]); --pos) {}
       str.resize(pos + 1); // note that pos + 1 can be 0
       return str;
     }
 
     ScaleFunction parse_ScaleFunction(
         std::string const & scale_fun
     ){
       assert(
           scale_fun.empty() ||
           (!std::isspace(scale_fun.front()) && !std::isspace(scale_fun.back()))
       );
       const size_t delim = scale_fun.find_first_of("*/");
       if(delim == scale_fun.npos){
         return parse_simple_ScaleFunction(scale_fun);
       }
       const std::string first = trim_back(std::string{scale_fun, 0, delim});
       const std::string second = trim_front(std::string{scale_fun, delim+1});
       double factor;
       ScaleFunction fun;
       if(scale_fun[delim] == '/'){
         factor = 1/to_double(second);
         fun = parse_simple_ScaleFunction(first);
       }
       else{
         assert(scale_fun[delim] == '*');
         try{
           factor = to_double(second);
           fun = parse_simple_ScaleFunction(first);
         }
         catch(std::invalid_argument const &){
           factor = to_double(first);
           fun = parse_simple_ScaleFunction(second);
         }
       }
       assert(fun != nullptr);
       return Product{factor, std::move(fun)};
     }
 
     EventTreatMap get_event_treatment(
         YAML::Node const & yaml
     ){
       using namespace event_type;
       EventTreatMap treat {
         {no_2_jets, EventTreatment::discard},
         {bad_final_state, EventTreatment::discard},
         {FKL, EventTreatment::reweight},
         {unob, EventTreatment::keep},
         {unof, EventTreatment::keep},
         {nonFKL, EventTreatment::keep}
       };
       set_from_yaml(treat.at(FKL), yaml, "FKL");
       set_from_yaml(treat.at(unob), yaml, "unordered");
       treat.at(unof) = treat.at(unob);
       set_from_yaml(treat.at(nonFKL), yaml, "non-FKL");
       if(treat[nonFKL] == EventTreatment::reweight){
         throw std::invalid_argument{"Cannot reweight non-FKL events"};
       }
       return treat;
     }
 
 
     Config to_Config(YAML::Node const & yaml){
       try{
         assert_all_options_known(yaml, get_supported_options());
       }
       catch(unknown_option const & ex){
         throw unknown_option{std::string{"Unknown option '"} + ex.what() + "'"};
       }
 
       Config config;
       config.resummation_jets = get_jet_parameters(yaml, "resummation jets");
       config.fixed_order_jets = config.resummation_jets;
       update_fixed_order_jet_parameters(config.fixed_order_jets, yaml);
       set_from_yaml(config.min_extparton_pt, yaml, "min extparton pt");
       config.max_ext_soft_pt_fraction = std::numeric_limits<double>::infinity();
       set_from_yaml_if_defined(
           config.max_ext_soft_pt_fraction, yaml, "max ext soft pt fraction"
       );
       set_from_yaml(config.trials, yaml, "trials");
       set_from_yaml(config.log_correction, yaml, "log correction");
       set_from_yaml(config.unweight, yaml, "unweight");
       config.treat = get_event_treatment(yaml);
       set_from_yaml_if_defined(config.output, yaml, "event output");
       set_from_yaml_if_defined(config.RanLux_init, yaml, "RanLux init");
       set_from_yaml_if_defined(config.analysis_parameters, yaml, "analysis");
       config.scales = to_ScaleConfig(yaml);
       config.Higgs_coupling = get_Higgs_coupling(yaml, "Higgs coupling");
       return config;
     }
 
   } // namespace anonymous
 
   ScaleConfig to_ScaleConfig(YAML::Node const & yaml){
     ScaleConfig config;
     std::vector<std::string> scales;
     set_from_yaml(scales, yaml, "scales");
     config.base.reserve(scales.size());
     std::transform(
         begin(scales), end(scales), std::back_inserter(config.base),
         parse_ScaleFunction
     );
     set_from_yaml_if_defined(config.factors, yaml, "scale factors");
     config.max_ratio = std::numeric_limits<double>::infinity();
     set_from_yaml_if_defined(config.max_ratio, yaml, "max scale ratio");
     return config;
   }
 
   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;
     }
   }
 
 } // namespace RHEJ