diff --git a/Changes.md b/Changes.md index 13b97c2..4b951f0 100644 --- a/Changes.md +++ b/Changes.md @@ -1,207 +1,208 @@ # Changelog This is the log for changes to the HEJ program. Further changes to the HEJ API are documented in [`Changes-API.md`](Changes-API.md). If you are using HEJ as a library, please also read the changes there. ## Version 2.2 This release adds support for the new processes: * Wp+Wp with jets. * Wm+Wm with jets. In addition, there are new options when running HEJ: * Enable NLO truncation for use in HEJ@NLO predictions. * Require a lowpt jet, used for running lowpt separately. This release includes minor changes which affect users of HEJ as a library (see [`Changes-API.md`](Changes-API.md)). Compilation now requires a compiler supporting C++17. ### 2.2.0 #### New Processes * Resummation for WpWp/WmWm with jets, including interference between configurations. * Significantly improved description of Higgs boson plus jet production: - Processes with extremal Higgs boson emission are now treated as leading-log. - Resummation is now enabled for Higgs boson production with a single jet. * `HEJFOG` can generate multiple jets together with a charged lepton-antilepton pair via a virtual Z boson or photon. #### Updates to configuration file * With the new option `off-shell tolerance` HEJ repairs the momenta of massless particles that are slightly off-shell and incoming particles with small but non-vanishing transverse momenta. * Introduced new event types `unknown` and `invalid` under the `event treatment` option. `unknown` indicates processes that are not recognised by HEJ. `invalid` is reserved for unphysical processes. * Introduced new event treatment `abort` for aborting the program when an undesired event type is encountered. * Removed the deprecated settings `min extparton pt` and `max ext soft pt fraction`. +* Removed the deprecated `analysis` setting. #### Changes to input/output * Event reader supports event input from named pipes (fifo) ## Version 2.1 This release adds support for two new processes: * W boson with jets. * Jets with a charged lepton-antilepton pair via a virtual Z boson or photon. In addition, the complete set of first subleading processes (unordered gluon, central and extremal quark-antiquark pair) is implemented for pure jets and W + jets, see [arXiv:2012.10310](https://arxiv.org/abs/2012.10310). Unordered gluon emission is also supported for Higgs boson + jets and Z boson/photon + jets. This release include many changes to the code, which affect users of HEJ as a library (see [`Changes-API.md`](Changes-API.md)). ### 2.1.3 * Updated documentation. ### 2.1.2 * Updated `cxxopts.hpp` dependency. ### 2.1.1 * Fixed invalid iterator accesses. * Reorganised automated tests. * Updated documentation. ### 2.1.0 #### New Processes * Resummation for W bosons with jets - New subleading processes `extremal qqbar` & `central qqbar` for a quark and anti-quark in the final state, e.g. `g g => u d_bar Wm g` (the other subleading processes also work with W's) - `HEJFOG` can generate multiple jets together with a (off-shell) W bosons decaying into lepton & neutrino * Resummation for jets with a charged lepton-antilepton pair via a virtual Z boson or photon. Includes the `unordered` subleading process. * Resummation can now be performed on all subleading processes within pure jets also. This includes `unordered`, `extremal qqbar` and `central qqbar` processes. #### More Physics implementation * Partons now have a Colour charge - Colours are read from and written to LHE files - For reweighted events the colours are created according to leading colour in the FKL limit * Use relative fraction for soft transverse momentum in tagging jets (`soft pt regulator`) as new (optional) parameter. - This supersedes `min extparton pt`, which is marked **deprecated** and will be removed in version 2.2.0 - This is a direct replacement for the old `max ext soft pt fraction`, which is also **deprecated**. * Changed the redistribution of the momenta of soft emissions. Now also bosons can take part of the recoil (previously only jets). #### Updates to Runcard * Allow multiplication and division of multiple scale functions e.g. `H_T/2*m_j1j2` * Grouped `event treatment` for subleading channels together in runcard - Rename `non-HEJ` processes to `non-resummable` * Read electro-weak constants from input - new mandatory setting `vev` to change vacuum expectation value - new mandatory settings `particle properties` to specify mass & width of bosons - `HEJFOG`: decays are now specified in `decays` setting (previously under `particle properties`) * Allow loading multiple analyses with `analyses`. The old `analysis` (with "i") is marked **deprecated**. * Optional setting to specify maximal number of Fixed Order events (`max events`, default is all) * Allow changing the regulator lambda in input (`regulator parameter`, only for advanced users) #### Changes to Input/Output * Added support to read & write `hdf5` event files suggested in [arXiv:1905.05120](https://arxiv.org/abs/1905.05120) (needs [HighFive](https://github.com/BlueBrain/HighFive)) * Support input with average weight equal to the cross section (`IDWTUP=1 or 4`) * Support unmodified Les Houches Event Files written by Sherpa with `cross section = sum(weights)/sum(trials)` * Analyses now get general run information (`LHEF::HEPRUP`) in the constructor. **This might break previously written, external analyses!** - external analyses should now be created with `make_analysis(YAML::Node const & config, LHEF::HEPRUP const & heprup)` * Support `rivet` version 3 with both `HepMC` version 2 and 3 - Multiple weights with `rivet 3` will only create one `.yoda` file (instead of one per weight/scale) * Added option to unweight only resummation events (`unweight: {type: resummation}`) * Added option for partially unweighting resummation events, similar to the fixed-order generator. * Improved unweighting algorithm. * Follow HepMC convention for particle Status codes: incoming = 11, decaying = 2, outgoing = 1 (unchanged) #### Miscellaneous * Print cross sections at end of run * Added example analysis & scale to `examples/`. Everything in `examples/` will be build when the flag `-DBUILD_EXAMPLES=TRUE` is set in `cmake`. * Dropped support for HepMC 3.0.0, either HepMC version 2 or >3.1 is required - It is now possible to write out both HepMC 2 and HepMC 3 events at the same time * Require LHADPF version 6. Dropped support for all other versions. * Use `git-lfs` for raw data in test (`make test` now requires `git-lfs`) * Currents are now generated with [`FORM`](https://github.com/vermaseren/form) - `FORM` is included as a `git submodule`, use `git submodule update --init` to download `FORM` * Create [Sphinx](http://sphinx-doc.org/) and [Doxygen](http://doxygen.org/) documentation by `make sphinx` or `make doxygen` in your `build/` folder ## Version 2.0 First release of HEJ 2. Complete code rewrite compared to HEJ 1. Improved matching to Fixed Order ([arXiv:1805.04446](https://arxiv.org/abs/1805.04446)). Implemented processes: Higgs boson with jets (FKL and unordered gluon emission, with finite quark mass loop, [arXiv:1812.08072](https://arxiv.org/abs/1812.08072)), and pure jets (only FKL). See [arXiv:1902.08430](https://arxiv.org/abs/1902.08430) ## 2.0.7 * Added missing `#include` directives. ### 2.0.6 * Fixed compiling rivet when YODA headers are _outside_ of rivet directory. ### 2.0.5 * Fixed event classification for input not ordered in rapidity. ### 2.0.4 * Fixed wrong path of `HEJ_INCLUDE_DIR` in `hej-config.cmake`. ### 2.0.3 * Fixed parsing of (numerical factor) * (base scale) in configuration. * Don't change scale names, but sanitise Rivet output file names instead. ### 2.0.2 * Changed scale names to `"_over_"` and `"_times_"` for proper file names (was `"/"` and `"*"` before). ### 2.0.1 * Fixed name of fixed-order generator in error message. ### 2.0.0 * First release. diff --git a/FixedOrderGen/src/config.cc b/FixedOrderGen/src/config.cc index 3cdff3b..429080d 100644 --- a/FixedOrderGen/src/config.cc +++ b/FixedOrderGen/src/config.cc @@ -1,488 +1,478 @@ /** * \authors The HEJ collaboration (see AUTHORS for details) * \date 2019-2020 * \copyright GPLv2 or later */ #include "config.hh" #include #include #include #include #include #include #include #include #include "HEJ/PDG_codes.hh" #include "HEJ/YAMLreader.hh" #include "HEJ/exceptions.hh" #include "HEJ/Event.hh" namespace HEJFOG { using HEJ::set_from_yaml; using HEJ::set_from_yaml_if_defined; using HEJ::pid::ParticleID; namespace { //! Convert name of channel in config to name of subleading process in HEJ size_t channel_to_subleading( unsigned const channel ){ using namespace HEJ::event_type; using namespace HEJFOG::subleading; switch (channel){ case uno: return unob; case cqqbar: return qqbar_mid; case eqqbar: return qqbar_exb; default: throw std::logic_error{"Invalid subleading channel"}; } } //! Check subleading processes implemented in HEJ2 bool is_valid_subleading( std::optional const boson, Subleading const subleading_channels ){ std::vector bosons; if(boson){ HEJ::Particle indicator_boson; indicator_boson.type = *boson; bosons.push_back(indicator_boson); } size_t const valid_types = HEJ::implemented_types(bosons); for ( unsigned channel = subleading::first; channel<=subleading::last; ++channel ){ if (subleading_channels[channel]){ if ( !(channel_to_subleading(channel) & valid_types) ){ return false; } } } return true; } //! 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", "analyses", "analysis", "import scales" + "event output", "analyses", "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 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 split( std::string const & str, std::string const & delims ){ std::vector result; for(size_t begin = 0, end = 0; end != std::string::npos;){ begin = str.find_first_not_of(delims, end); if(begin == std::string::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 const & ids ){ assert(ids.size()==2); const int pidsum = ids[0] + ids[1]; switch(pidsum){ case +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; case -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; case 0: assert(HEJ::is_anylepton(ids[0])); if(HEJ::is_anyneutrino(ids[0])) { throw HEJ::not_implemented{"final state with two neutrinos"}; } // charged lepton-antilepton pair means we had a Z/photon return HEJ::pid::Z_photon_mix; default: throw HEJ::not_implemented{ "final state with leptons "+name(ids[0])+" and "+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::subleading; set_from_yaml(name, yaml); if(name == "none") return NONE; if(name == "all") return ALL; Subleading channel = NONE; if(name == "unordered" || name == "uno") return channel.set(uno); if(name == "central qqbar" || name == "cqqbar") return channel.set(cqqbar); if(name == "extremal qqbar" || name == "eqqbar") return channel.set(eqqbar); throw HEJ::unknown_option("Unknown subleading channel '"+name+"'"); } Subleading get_subleading_channels(YAML::Node const & node){ using YAML::NodeType; using namespace HEJFOG::subleading; if(!node) throw std::invalid_argument{"Subleading channels must be specified"}; switch(node.Type()){ case NodeType::Undefined: case NodeType::Null: throw std::invalid_argument("Subleading channels must be specified"); 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: Subleading channels; 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, std::string const & entry, std::string const & boson ){ Decay decay; set_from_yaml(decay.products, node, entry, boson, "into"); decay.branching_ratio=1; set_from_yaml_if_defined(decay.branching_ratio, node, entry, boson, "branching ratio"); return decay; } std::vector get_decays(YAML::Node const & node, std::string const & entry, std::string const & boson ){ using YAML::NodeType; if(!node[entry][boson]) return {}; switch(node[entry][boson].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, entry, boson)}; case NodeType::Sequence: std::vector result; for(auto && decay_str: node[entry][boson]){ result.emplace_back(get_decay(decay_str, entry, boson)); } 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 boson = sub_node.first.as(); const auto id = HEJ::to_ParticleID(boson); result.emplace(id, get_decays(node, entry, boson)); } 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){ auto const & 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_channels.reset(); else config.subleading_channels = get_subleading_channels(yaml["subleading channels"]); //check to see if subleading channels allowed for given process if (!is_valid_subleading( config.process.boson, config.subleading_channels ) ){ throw HEJ::not_implemented{ "Invalid subleading channels for given process" }; } config.ew_parameters = HEJ::get_ew_parameters(yaml); config.particle_decays = get_all_decays(yaml, "decays"); if(config.process.boson // check that Ws always decay && std::abs(*config.process.boson) == HEJ::ParticleID::Wp && config.process.boson_decay.empty() ){ auto const & decay = config.particle_decays.find(*config.process.boson); if(decay == config.particle_decays.end() || decay->second.empty()) throw std::invalid_argument{ "Decay for "+name(*config.process.boson)+" is required"}; } set_from_yaml_if_defined(config.analyses_parameters, yaml, "analyses"); - if(yaml["analysis"].IsDefined()){ - std::cerr << - "WARNING: Configuration entry 'analysis' is deprecated. " - " Use 'analyses' instead.\n"; - YAML::Node ana; - set_from_yaml(ana, yaml, "analysis"); - if(!ana.IsNull()){ - config.analyses_parameters.push_back(ana); - } - } 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"].IsDefined()) config.unweight = get_unweight(yaml, "unweight"); return config; } } // namespace 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 HEJFOG diff --git a/include/HEJ/Config.hh b/include/HEJ/Config.hh index 8a8b2ea..85ebf72 100644 --- a/include/HEJ/Config.hh +++ b/include/HEJ/Config.hh @@ -1,274 +1,271 @@ /** \file * \brief HEJ 2 configuration parameters * * \authors The HEJ collaboration (see AUTHORS for details) * \date 2019-2022 * \copyright GPLv2 or later */ #pragma once #include #include #include #include #include #include "fastjet/JetDefinition.hh" #include "yaml-cpp/yaml.h" #include "HEJ/Constants.hh" #include "HEJ/EWConstants.hh" #include "HEJ/Fraction.hh" #include "HEJ/HiggsCouplingSettings.hh" #include "HEJ/ScaleFunction.hh" #include "HEJ/event_types.hh" #include "HEJ/output_formats.hh" namespace HEJ { //! Jet parameters struct JetParameters{ fastjet::JetDefinition def; /**< Jet Definition */ double min_pt{}; /**< Minimum Jet Transverse Momentum */ }; //! Settings for scale variation struct ScaleConfig{ //! Base scale choices std::vector base; //! Factors for multiplicative scale variation std::vector factors; //! Maximum ratio between renormalisation and factorisation scale double max_ratio{}; }; //! Settings for random number generator struct RNGConfig { //! Random number generator name std::string name; //! Optional initial seed std::optional seed; }; //! Settings for partial unweighting struct PartialUnweightConfig { //! Number of trials for training size_t trials; //! Maximum distance in standard deviations from mean logarithmic weight double max_dev; }; //! Settings for HEJ@NLO struct NLOConfig { //! Settings for HEJ@NLO Truncation bool enabled = false; //! NLO Born number of jets size_t nj = 2; }; /**! Possible treatments for fixed-order input events. * * The program will decide on how to treat an event based on * the value of this enumeration. */ enum class EventTreatment{ reweight, /**< Perform resummation */ keep, /**< Keep the event */ discard, /**< Discard the event */ abort, /**< Throw an exception */ }; //! Container to store the treatments for various event types using EventTreatMap = std::map; //! Possible setting for the event weight enum class WeightType{ weighted, //!< weighted events unweighted_resum, //!< unweighted only resummation part partially_unweighted //!< mixed weighted and unweighted }; /**! Input parameters. * * This struct handles stores all configuration parameters * needed in a HEJ 2 run. * * \internal To add a new option: * 1. Add a member to the Config struct. * 2. Inside "src/YAMLreader.cc": * - Add the option name to the "supported" Node in * get_supported_options. * - Initialise the new Config member in to_Config. * The functions set_from_yaml (for mandatory options) and * set_from_yaml_if_defined (non-mandatory) may be helpful. * 3. Add a new entry (with short description) to config.yaml * 4. Update the user documentation in "doc/Sphinx/" */ struct Config { //! %Parameters for scale variation ScaleConfig scales; //! Resummation jet properties JetParameters resummation_jets; //! Fixed-order jet properties JetParameters fixed_order_jets; //! @brief Maximum transverse momentum fraction from soft radiation in any //! tagging jet (e.g. extremal or qqbar jet) Fraction soft_pt_regulator{ DEFAULT_SOFT_PT_REGULATOR }; //! The regulator lambda for the subtraction terms double regulator_lambda = CLAMBDA; //! Number of resummation configurations to generate per fixed-order event size_t trials{}; //! Maximal number of events std::optional max_events; //! Whether to include the logarithmic correction from \f$\alpha_s\f$ running bool log_correction{}; //! Event output files names and formats std::vector output; //! Parameters for random number generation RNGConfig rng; //! Map to decide what to do for different event types EventTreatMap treat; - //! %Parameters for custom analysis - //! @deprecated use analyses_parameters instead - YAML::Node analysis_parameters; //! %Parameters for custom analyses std::vector analyses_parameters; //! Settings for effective Higgs-gluon coupling HiggsCouplingSettings Higgs_coupling; //! elector weak parameters EWConstants ew_parameters; //! Type of event weight e.g. (un)weighted WeightType weight_type; //! Settings for partial unweighting std::optional unweight_config; //! HEJ@NLO settings NLOConfig nlo; //! LowPT settings bool lowpt = false; //! Tolerance towards numerical inaccuracies in input momenta double off_shell_tolerance = 0.; }; //! Configuration options for the PhaseSpacePoint class struct PhaseSpacePointConfig { PhaseSpacePointConfig() = default; PhaseSpacePointConfig( JetParameters jet_param, NLOConfig nlo, Fraction soft_pt_regulator = Fraction{DEFAULT_SOFT_PT_REGULATOR} ): jet_param{std::move(jet_param)}, nlo{std::move(nlo)}, soft_pt_regulator{std::move(soft_pt_regulator)} {} //! Properties of resummation jets JetParameters jet_param; //! HEJ@NLO settings NLOConfig nlo; //! @brief Maximum transverse momentum fraction from soft radiation in any //! tagging jet (e.g. extremal or qqbar jet) Fraction soft_pt_regulator{ DEFAULT_SOFT_PT_REGULATOR }; }; //! Configuration options for the MatrixElement class struct MatrixElementConfig { MatrixElementConfig() = default; MatrixElementConfig( bool log_correction, HiggsCouplingSettings Higgs_coupling, EWConstants ew_parameters, NLOConfig nlo, Fraction soft_pt_regulator = Fraction{DEFAULT_SOFT_PT_REGULATOR}, double regulator_lambda = CLAMBDA ): log_correction{log_correction}, Higgs_coupling{std::move(Higgs_coupling)}, ew_parameters{std::move(ew_parameters)}, nlo{std::move(nlo)}, soft_pt_regulator{soft_pt_regulator}, regulator_lambda{regulator_lambda} {} //! Whether to include the logarithmic correction from \f$\alpha_s\f$ running bool log_correction{}; //! Settings for effective Higgs-gluon coupling HiggsCouplingSettings Higgs_coupling; //! elector weak parameters EWConstants ew_parameters; //! HEJ@NLO settings NLOConfig nlo; //! @brief Maximum transverse momentum fraction from soft radiation in any //! tagging jet (e.g. extremal or qqbar jet) Fraction soft_pt_regulator{ DEFAULT_SOFT_PT_REGULATOR }; //! The regulator lambda for the subtraction terms double regulator_lambda = CLAMBDA; }; //! Configuration options for the EventReweighter class struct EventReweighterConfig { //! Settings for phase space point generation PhaseSpacePointConfig psp_config; //! Settings for matrix element calculation MatrixElementConfig ME_config; //! Access properties of resummation jets JetParameters & jet_param() { return psp_config.jet_param;} //! Access properties of resummation jets (const version) JetParameters const & jet_param() const { return psp_config.jet_param;} //! Treatment of the various event types EventTreatMap treat; //! Option to only keep lowpt contribution bool lowpt = false; }; /**! Extract PhaseSpacePointConfig from Config * * \internal We do not provide a PhaseSpacePointConfig constructor from Config * so that PhaseSpacePointConfig remains an aggregate. * This faciliates writing client code (e.g. the HEJ fixed-order generator) * that creates a PhaseSpacePointConfig *without* a Config object. * * @see to_MatrixElementConfig, to_EventReweighterConfig */ inline PhaseSpacePointConfig to_PhaseSpacePointConfig(Config const & conf) { return { conf.resummation_jets, conf.nlo, conf.soft_pt_regulator }; } /**! Extract MatrixElementConfig from Config * * @see to_PhaseSpacePointConfig, to_EventReweighterConfig */ inline MatrixElementConfig to_MatrixElementConfig(Config const & conf) { return { conf.log_correction, conf.Higgs_coupling, conf.ew_parameters, conf.nlo, conf.soft_pt_regulator, conf.regulator_lambda }; } /**! Extract EventReweighterConfig from Config * * @see to_PhaseSpacePointConfig, to_MatrixElementConfig */ inline EventReweighterConfig to_EventReweighterConfig(Config const & conf) { return { to_PhaseSpacePointConfig(conf), to_MatrixElementConfig(conf), conf.treat, conf.lowpt }; } } // namespace HEJ diff --git a/src/YAMLreader.cc b/src/YAMLreader.cc index 6b17ad5..5845f53 100644 --- a/src/YAMLreader.cc +++ b/src/YAMLreader.cc @@ -1,593 +1,584 @@ /** * \authors The HEJ collaboration (see AUTHORS for details) * \date 2019-2020 * \copyright GPLv2 or later */ #include "HEJ/YAMLreader.hh" #include #include #include #include #include #include #include #include #include "HEJ/ConfigFlags.hh" #include "HEJ/Constants.hh" #include "HEJ/ScaleFunction.hh" #include "HEJ/event_types.hh" #include "HEJ/output_formats.hh" namespace HEJ { class Event; 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", "soft pt regulator", "scales", "scale factors", "max scale ratio", "import scales", - "log correction", "event output", "analysis", "analyses", "vev", + "log correction", "event output", "analyses", "vev", "regulator parameter", "max events", "off-shell tolerance", "require low pt jet" }; // 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] = ""; } for(auto && opt: {"name", "seed"}){ supported["random generator"][opt] = ""; } for(auto && opt: {"enabled", "nlo order"}){ supported["NLO truncation"][opt] = ""; } for( auto && opt: { "FKL", "unordered", "extremal qqbar", "central qqbar", "non-resummable", "unknown", "invalid" }){ supported["event treatment"][opt] = ""; } for(auto && particle_type: {"Higgs", "W", "Z"}){ for(auto && particle_opt: {"mass", "width"}){ supported["particle properties"][particle_type][particle_opt] = ""; } } for(auto && opt: {"type", "trials", "max deviation"}){ supported["unweight"][opt] = ""; } return supported; }(); return supported; } fastjet::JetAlgorithm to_JetAlgorithm(std::string const & algo){ using namespace fastjet; static const std::map known = { {"kt", kt_algorithm}, {"cambridge", cambridge_algorithm}, {"antikt", antikt_algorithm}, {"cambridge for passive", cambridge_for_passive_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 known = { {"reweight", EventTreatment::reweight}, {"keep", EventTreatment::keep}, {"discard", EventTreatment::discard}, {"abort", EventTreatment::abort} }; const auto res = known.find(name); if(res == known.end()){ throw std::invalid_argument("Unknown event treatment \"" + name + "\""); } return res->second; } WeightType to_weight_type(std::string const & setting){ if(setting == "weighted") return WeightType::weighted; if(setting =="resummation") return WeightType::unweighted_resum; if(setting =="partial") return WeightType::partially_unweighted; throw std::invalid_argument{"Unknown weight type \"" + setting + "\""}; } } // namespace namespace detail{ void set_from_yaml(fastjet::JetAlgorithm & setting, YAML::Node const & yaml){ setting = to_JetAlgorithm(yaml.as()); } void set_from_yaml(EventTreatment & setting, YAML::Node const & yaml){ setting = to_EventTreatment(yaml.as()); } void set_from_yaml(ParticleID & setting, YAML::Node const & yaml){ setting = to_ParticleID(yaml.as()); } void set_from_yaml(WeightType & setting, YAML::Node const & yaml){ setting = to_weight_type(yaml.as()); } } // 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 = NAN; 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; } RNGConfig to_RNGConfig( YAML::Node const & node, std::string const & entry ){ assert(node); RNGConfig result; set_from_yaml(result.name, node, entry, "name"); set_from_yaml_if_defined(result.seed, node, entry, "seed"); return result; } NLOConfig to_NLOConfig( YAML::Node const & node, std::string const & entry ){ assert(node); NLOConfig result; set_from_yaml_if_defined(result.enabled, node, entry, "enabled"); set_from_yaml_if_defined(result.nj, node, entry, "nlo order"); return result; } ParticleProperties get_particle_properties( YAML::Node const & node, std::string const & entry, std::string const & boson ){ ParticleProperties result{}; set_from_yaml(result.mass, node, entry, boson, "mass"); set_from_yaml(result.width, node, entry, boson, "width"); return result; } EWConstants get_ew_parameters(YAML::Node const & node){ EWConstants result; double vev = NAN; 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; } HiggsCouplingSettings get_Higgs_coupling( YAML::Node const & node, std::string const & entry ){ assert(node); static constexpr double mt_max = 2e4; #ifndef HEJ_BUILD_WITH_QCDLOOP if(node[entry].IsDefined()){ throw std::invalid_argument{ "Higgs coupling settings require building HEJ 2 " "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::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 known = { {"Les Houches", FileFormat::Les_Houches}, {"HepMC", FileFormat::HepMC}, {"HepMC2", FileFormat::HepMC2}, {"HepMC3", FileFormat::HepMC3}, {"HDF5", FileFormat::HDF5} }; 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 == std::string::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; if(suffix == "hepmc3") return FileFormat::HepMC3; if(suffix == "hepmc2") return FileFormat::HepMC2; if(suffix == "hdf5") return FileFormat::HDF5; 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(); if(! supported[name]) throw unknown_option{name}; /* check sub-options, e.g. 'resummation jets: min pt' * we don't check analyses sub-options * those depend on the analysis being used and should be checked there * similar for "import scales" */ - if(name != "analyses" && name != "analysis" && name != "import scales"){ + if(name != "analyses" && name != "import scales"){ 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 HEJ namespace YAML { Node convert::encode(HEJ::OutputFile const & outfile) { Node node; node[to_string(outfile.format)] = outfile.name; return node; } bool convert::decode(Node const & node, HEJ::OutputFile & out) { switch(node.Type()){ case NodeType::Map: { YAML::const_iterator it = node.begin(); out.format = HEJ::to_FileFormat(it->first.as()); out.name = it->second.as(); return true; } case NodeType::Scalar: out.name = node.as(); out.format = HEJ::format_from_suffix(out.name); return true; default: return false; } } } // namespace YAML namespace HEJ { namespace detail{ void set_from_yaml(OutputFile & setting, YAML::Node const & yaml){ setting = yaml.as(); } } 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 = 0; const double result = std::stod(str, &pos); if(pos < str.size()){ throw std::invalid_argument(str + " is not a valid double value"); } return result; } using EventScale = double (*)(Event const &); void import_scale_functions( std::string const & file, std::vector const & scale_names, std::unordered_map & known ) { void * handle = dlopen(file.c_str(), RTLD_NOW); char * error = dlerror(); if(error != nullptr) throw std::runtime_error{error}; for(auto const & scale: scale_names) { void * sym = dlsym(handle, scale.c_str()); error = dlerror(); if(error != nullptr) throw std::runtime_error{error}; known.emplace(scale, reinterpret_cast(sym)); // NOLINT } } auto get_scale_map( YAML::Node const & yaml ) { std::unordered_map scale_map; scale_map.emplace("H_T", H_T); scale_map.emplace("max jet pperp", max_jet_pt); scale_map.emplace("jet invariant mass", jet_invariant_mass); scale_map.emplace("m_j1j2", m_j1j2); if(yaml["import scales"].IsDefined()) { if(! yaml["import scales"].IsMap()) { throw invalid_type{"Entry 'import scales' is not a map"}; } for(auto const & import: yaml["import scales"]) { const auto file = import.first.as(); const auto scale_names = import.second.IsSequence() ?import.second.as>() :std::vector{import.second.as()}; import_scale_functions(file, scale_names, scale_map); } } return scale_map; } // 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, std::unordered_map const & known ) { assert( scale_fun.empty() || (!std::isspace(scale_fun.front()) && !std::isspace(scale_fun.back())) ); const auto it = known.find(scale_fun); if(it != end(known)) return {it->first, it->second}; try{ const double scale = to_double(scale_fun); return {scale_fun, 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) == 0; } ); 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, std::unordered_map const & known ){ assert( scale_fun.empty() || (!std::isspace(scale_fun.front()) && !std::isspace(scale_fun.back())) ); // parse from right to left => a/b/c gives (a/b)/c const size_t delim = scale_fun.find_last_of("*/"); if(delim == std::string::npos){ return parse_simple_ScaleFunction(scale_fun, known); } const std::string first = trim_back(std::string{scale_fun, 0, delim}); const std::string second = trim_front(std::string{scale_fun, delim+1}); if(scale_fun[delim] == '/'){ return parse_ScaleFunction(first, known) / parse_ScaleFunction(second, known); } assert(scale_fun[delim] == '*'); return parse_ScaleFunction(first, known) * parse_ScaleFunction(second, known); } EventTreatMap get_event_treatment( YAML::Node const & node, std::string const & entry ){ using namespace event_type; EventTreatMap treat { {FKL, EventTreatment::discard}, {unob, EventTreatment::discard}, {unof, EventTreatment::discard}, {qqbar_exb, EventTreatment::discard}, {qqbar_exf, EventTreatment::discard}, {qqbar_mid, EventTreatment::discard}, {non_resummable, EventTreatment::discard}, {unknown, EventTreatment::abort}, {invalid, EventTreatment::abort} }; set_from_yaml(treat.at(FKL), node, entry, "FKL"); set_from_yaml(treat.at(unob), node, entry, "unordered"); treat.at(unof) = treat.at(unob); set_from_yaml(treat.at(qqbar_exb), node, entry, "extremal qqbar"); treat.at(qqbar_exf) = treat.at(qqbar_exb); set_from_yaml(treat.at(qqbar_mid), node, entry, "central qqbar"); set_from_yaml(treat.at(non_resummable), node, entry, "non-resummable"); set_from_yaml_if_defined(treat.at(unknown), node, entry, "unknown"); set_from_yaml_if_defined(treat.at(invalid), node, entry, "invalid"); for(auto type: {non_resummable, unknown, invalid}) { if(treat[type] == EventTreatment::reweight){ throw std::invalid_argument{"Cannot reweight " + name(type) + " 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_if_defined(config.soft_pt_regulator, yaml, "soft pt regulator"); // Sets the standard value, then changes this if defined config.regulator_lambda=CLAMBDA; set_from_yaml_if_defined(config.regulator_lambda, yaml, "regulator parameter"); set_from_yaml_if_defined(config.max_events, yaml, "max events"); set_from_yaml(config.trials, yaml, "trials"); config.weight_type = WeightType::weighted; set_from_yaml_if_defined(config.weight_type, yaml, "unweight", "type"); if(config.weight_type == WeightType::partially_unweighted) { config.unweight_config = PartialUnweightConfig{}; set_from_yaml( config.unweight_config->trials, yaml, "unweight", "trials" ); set_from_yaml( config.unweight_config->max_dev, yaml, "unweight", "max deviation" ); } else if(yaml["unweight"].IsDefined()) { for(auto && opt: {"trials", "max deviation"}) { if(yaml["unweight"][opt].IsDefined()) { throw std::invalid_argument{ "'unweight: " + std::string{opt} + "' " "is only supported if 'unweight: type' is set to 'partial'" }; } } } set_from_yaml(config.log_correction, yaml, "log correction"); config.treat = get_event_treatment(yaml, "event treatment"); set_from_yaml_if_defined(config.output, yaml, "event output"); config.rng = to_RNGConfig(yaml, "random generator"); set_from_yaml_if_defined(config.lowpt, yaml, "require low pt jet"); set_from_yaml_if_defined(config.analyses_parameters, yaml, "analyses"); - if(yaml["analysis"].IsDefined()){ - std::cerr << - "WARNING: Configuration entry 'analysis' is deprecated. " - " Use 'analyses' instead.\n"; - set_from_yaml(config.analysis_parameters, yaml, "analysis"); - if(!config.analysis_parameters.IsNull()){ - config.analyses_parameters.push_back(config.analysis_parameters); - } - } config.scales = to_ScaleConfig(yaml); config.ew_parameters = get_ew_parameters(yaml); config.Higgs_coupling = get_Higgs_coupling(yaml, "Higgs coupling"); //HEJ@NLO Truncation config.nlo = to_NLOConfig(yaml, "NLO truncation"); set_from_yaml_if_defined( config.off_shell_tolerance, yaml, "off-shell tolerance" ); return config; } } // namespace ScaleConfig to_ScaleConfig(YAML::Node const & yaml){ ScaleConfig config; auto scale_funs = get_scale_map(yaml); std::vector scales; set_from_yaml(scales, yaml, "scales"); config.base.reserve(scales.size()); std::transform( begin(scales), end(scales), std::back_inserter(config.base), [scale_funs](auto const & entry){ return parse_ScaleFunction(entry, scale_funs); } ); set_from_yaml_if_defined(config.factors, yaml, "scale factors"); config.max_ratio = std::numeric_limits::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 HEJ diff --git a/t/CMakeLists.txt b/t/CMakeLists.txt index c47bd7c..5f4f145 100644 --- a/t/CMakeLists.txt +++ b/t/CMakeLists.txt @@ -1,707 +1,707 @@ set(tst_dir "${CMAKE_CURRENT_SOURCE_DIR}") set(tst_ME_data_dir "${tst_dir}/ME_data") # small library for common test functions add_library(hej_test SHARED hej_test.cc) target_include_directories(hej_test PUBLIC ${tst_dir}) target_link_libraries(hej_test HEJ) # test event classification # test explicit configurations add_executable(test_classify ${tst_dir}/test_classify.cc) target_compile_options(test_classify PRIVATE "-O0") # avoid compiler optimisation target_link_libraries(test_classify HEJ hej_test) add_test( NAME classify COMMAND test_classify ) # test against reference data add_executable(test_classify_ref ${tst_dir}/test_classify_ref.cc) target_link_libraries(test_classify_ref HEJ hej_test) add_test( NAME classify_ref COMMAND test_classify_ref ${tst_dir}/classify_ref ${tst_dir}/classify.lhe.gz ) add_test( NAME classify_ref_4j COMMAND test_classify_ref ${tst_dir}/classify_ref_4j ${tst_dir}/4j.lhe.gz ) add_test( NAME classify_ref_W4j COMMAND test_classify_ref ${tst_dir}/classify_ref_W4j ${tst_dir}/MGemnubar4j_unweighted.lhe.gz ) add_test( NAME t_classify_ref_Z4j COMMAND test_classify_ref ${tst_dir}/classify_ref_Z4j ${tst_dir}/Z_4j.lhe.gz ) # test for valid W decays add_executable(test_decay ${tst_dir}/test_decay.cc) target_link_libraries(test_decay HEJ hej_test) add_test( NAME valid_decay COMMAND test_decay ) # test valid jet cuts on tagging jets add_executable(test_jet_cuts ${tst_dir}/test_jet_cuts.cc) target_link_libraries(test_jet_cuts HEJ hej_test) add_test( NAME jet_cuts COMMAND test_jet_cuts ) # test phase space point add_executable(test_psp ${tst_dir}/test_psp.cc) target_link_libraries(test_psp HEJ hej_test) add_test( NAME PhaseSpace COMMAND test_psp ${tst_dir}/psp_gen.lhe.gz ) # test importing analyses file(COPY "${tst_dir}/analysis_config.yml" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}") set(test_config "${CMAKE_CURRENT_BINARY_DIR}/analysis_config.yml") get_target_property(ANALYSIS_PATH AnalysisTemplate_lib BINARY_DIR) get_target_property(ANALYSIS_LIB AnalysisTemplate_lib OUTPUT_NAME) set(ANALYSIS_PARAMETERS "") file(READ ${test_config} config) file(WRITE ${test_config} "${config} - plugin: ${ANALYSIS_PATH}/lib${ANALYSIS_LIB}.so\n ${ANALYSIS_PARAMETERS}\n") configure_file( ${tst_dir}/analysis_config_single.yml.in analysis_config_simple.yml @ONLY ) add_test( NAME analysis_simple COMMAND $ analysis_config_simple.yml ${tst_dir}/2j.lhe.gz ) get_target_property(ANALYSIS_PATH AnalysisPrint_lib BINARY_DIR) get_target_property(ANALYSIS_LIB AnalysisPrint_lib OUTPUT_NAME) set(ANALYSIS_PARAMETERS " output: ana_output") file(READ ${test_config} config) file(WRITE ${test_config} "${config} - plugin: ${ANALYSIS_PATH}/lib${ANALYSIS_LIB}.so\n ${ANALYSIS_PARAMETERS}\n") configure_file( ${tst_dir}/analysis_config_single.yml.in analysis_config_print.yml @ONLY ) add_test( NAME analysis_print COMMAND $ analysis_config_print.yml ${tst_dir}/2j.lhe.gz ) if(ROOT_FOUND) get_target_property(ANALYSIS_PATH AnalysisROOT_lib BINARY_DIR) get_target_property(ANALYSIS_LIB AnalysisROOT_lib OUTPUT_NAME) set(ANALYSIS_PARAMETERS "") file(READ ${test_config} config) file(WRITE ${test_config} "${config} - plugin: ${ANALYSIS_PATH}/lib${ANALYSIS_LIB}.so\n ${ANALYSIS_PARAMETERS}\n") configure_file( ${tst_dir}/analysis_config_single.yml.in analysis_config_root.yml @ONLY ) add_test( NAME analysis_root COMMAND $ analysis_config_root.yml ${tst_dir}/2j.lhe.gz ) endif() if(RIVET_FOUND) file(READ ${test_config} config) file(WRITE ${test_config} "${config} - rivet: MC_XS\n output: ana_rivet\n") endif() add_test( NAME analysis_all COMMAND $ ${test_config} ${tst_dir}/2j.lhe.gz ) # test importing scales (from examples/softestptScale) add_executable(test_scale_import ${tst_dir}/test_scale_import.cc) target_link_libraries(test_scale_import HEJ) get_target_property(SCALE_PATH softestptScale_lib BINARY_DIR) get_target_property(SCALE_LIB softestptScale_lib OUTPUT_NAME) set(SCALE_NAME "softest_jet_pt") configure_file( ${tst_dir}/jet_config_with_import.yml.in jet_config_with_import.yml @ONLY ) add_test( NAME scale_import COMMAND test_scale_import jet_config_with_import.yml ) # test scale arithmetic (e.g. 2*H_T/4) add_executable(test_scale_arithmetics ${tst_dir}/test_scale_arithmetics.cc) target_link_libraries(test_scale_arithmetics HEJ hej_test) add_test( NAME scale_arithmetics COMMAND test_scale_arithmetics ${tst_dir}/jet_config.yml ${tst_dir}/2j.lhe.gz ) # test "ParameterDescription" add_executable(test_descriptions ${tst_dir}/test_descriptions.cc) target_link_libraries(test_descriptions HEJ hej_test) add_test( NAME descriptions COMMAND test_descriptions ) # test "EventParameters*Weight" add_executable(test_parameters ${tst_dir}/test_parameters.cc) target_link_libraries(test_parameters HEJ hej_test) add_test( NAME parameters COMMAND test_parameters ) # test Particle IDs add_executable(test_pid ${tst_dir}/test_pid.cc) target_link_libraries(test_pid HEJ hej_test) add_test( NAME pid COMMAND test_pid ) # test EW constants add_executable(test_EWConstants ${tst_dir}/test_EWConstants.cc) target_link_libraries(test_EWConstants HEJ hej_test) add_test( NAME EWConstants COMMAND test_EWConstants ) # test unweighting add_executable(test_unweighter ${tst_dir}/test_unweighter.cc) target_link_libraries(test_unweighter HEJ hej_test) add_test( NAME unweighter COMMAND test_unweighter ${tst_dir}/4j.lhe.gz ) # test colour generation add_executable(test_colours ${tst_dir}/test_colours.cc) target_link_libraries(test_colours HEJ hej_test) add_test( NAME colour_flow COMMAND test_colours ) add_executable(test_colours2 ${tst_dir}/test_colours2.cc) target_link_libraries(test_colours2 HEJ hej_test) add_test( NAME colour_flow2 COMMAND test_colours2 ) # test matrix elements add_executable(test_ME_generic ${tst_dir}/test_ME_generic.cc) target_link_libraries(test_ME_generic HEJ hej_test) add_test( NAME ME_j COMMAND test_ME_generic ${tst_ME_data_dir}/config_mtinf.yml ${tst_ME_data_dir}/ME_jets_tree.dat ${tst_ME_data_dir}/PSP_jets.lhe.gz ) add_test( NAME ME_j_virt COMMAND test_ME_generic ${tst_ME_data_dir}/config_mtinf.yml ${tst_ME_data_dir}/ME_jets_tree_virt.dat ${tst_ME_data_dir}/PSP_jets.lhe.gz ) add_test( NAME ME_h COMMAND test_ME_generic ${tst_ME_data_dir}/config_mtinf.yml ${tst_ME_data_dir}/ME_h_mtinf_tree.dat ${tst_ME_data_dir}/PSP_h.lhe.gz ) add_test( NAME ME_h_subl COMMAND test_ME_generic ${tst_ME_data_dir}/config_mtinf.yml ${tst_ME_data_dir}/ME_h_subl_mtinf_tree.dat ${tst_ME_data_dir}/PSP_h_subl.lhe.gz ) add_test( NAME ME_hj COMMAND test_ME_generic ${tst_ME_data_dir}/config_mtinf.yml ${tst_ME_data_dir}/ME_hj_mtinf_tree.dat ${tst_ME_data_dir}/PSP_hj.lhe.gz ) add_test( NAME ME_h_virt COMMAND test_ME_generic ${tst_ME_data_dir}/config_mtinf.yml ${tst_ME_data_dir}/ME_h_mtinf_virt.dat ${tst_ME_data_dir}/PSP_h.lhe.gz ) add_test( NAME ME_hj_virt COMMAND test_ME_generic ${tst_ME_data_dir}/config_mtinf.yml ${tst_ME_data_dir}/ME_hj_mtinf_virt.dat ${tst_ME_data_dir}/PSP_hj.lhe.gz ) if(QCDloop_FOUND) add_test( NAME ME_h_mt COMMAND test_ME_generic ${tst_ME_data_dir}/config_mt.yml ${tst_ME_data_dir}/ME_h_mt_tree.dat ${tst_ME_data_dir}/PSP_h.lhe.gz ) add_test( NAME ME_h_mtmb COMMAND test_ME_generic ${tst_ME_data_dir}/config_mtmb.yml ${tst_ME_data_dir}/ME_h_mtmb_tree.dat ${tst_ME_data_dir}/PSP_h.lhe.gz ) add_test( NAME ME_h_subl_mtmb COMMAND test_ME_generic ${tst_ME_data_dir}/config_mtmb.yml ${tst_ME_data_dir}/ME_h_subl_mtmb_tree.dat ${tst_ME_data_dir}/PSP_h_subl.lhe.gz ) add_test( NAME ME_hj_mt COMMAND test_ME_generic ${tst_ME_data_dir}/config_mt.yml ${tst_ME_data_dir}/ME_hj_mt_tree.dat ${tst_ME_data_dir}/PSP_hj.lhe.gz ) add_test( NAME ME_hj_mtmb COMMAND test_ME_generic ${tst_ME_data_dir}/config_mtmb.yml ${tst_ME_data_dir}/ME_hj_mtmb_tree.dat ${tst_ME_data_dir}/PSP_hj.lhe.gz ) endif() add_test( NAME ME_j_subl COMMAND test_ME_generic ${tst_ME_data_dir}/config_pure.yml ${tst_ME_data_dir}/ME_jets_subl_tree.dat ${tst_ME_data_dir}/PSP_jets_subl.lhe.gz ) add_test( NAME ME_j_subl_virt COMMAND test_ME_generic ${tst_ME_data_dir}/config_pure.yml ${tst_ME_data_dir}/ME_jets_subl_tree_virt.dat ${tst_ME_data_dir}/PSP_jets_subl.lhe.gz ) add_test( NAME ME_j_subl_4j COMMAND test_ME_generic ${tst_ME_data_dir}/config_pure.yml ${tst_ME_data_dir}/ME_jets_subl_tree_new.dat ${tst_dir}/4j.lhe.gz ) add_test( NAME ME_j_subl_4j_virt COMMAND test_ME_generic ${tst_ME_data_dir}/config_pure.yml ${tst_ME_data_dir}/ME_jets_subl_tree_new_virt.dat ${tst_dir}/4j.lhe.gz ) add_test( NAME ME_w_FKL COMMAND test_ME_generic ${tst_ME_data_dir}/config_w_ME.yml ${tst_ME_data_dir}/ME_w_FKL_tree.dat ${tst_ME_data_dir}/PSP_w_FKL.lhe.gz ) add_test( NAME ME_w_FKL_virt COMMAND test_ME_generic ${tst_ME_data_dir}/config_w_ME.yml ${tst_ME_data_dir}/ME_w_FKL_virt.dat ${tst_ME_data_dir}/PSP_w_FKL.lhe.gz ) add_test( NAME ME_Wp COMMAND test_ME_generic ${tst_ME_data_dir}/config_w_ME.yml ${tst_ME_data_dir}/ME_Wp.dat ${tst_ME_data_dir}/PSP_Wp.lhe.gz ) add_test( NAME ME_Wp_virt COMMAND test_ME_generic ${tst_ME_data_dir}/config_w_ME.yml ${tst_ME_data_dir}/ME_Wp_virt.dat ${tst_ME_data_dir}/PSP_Wp.lhe.gz ) add_test( NAME ME_Wm COMMAND test_ME_generic ${tst_ME_data_dir}/config_w_ME.yml ${tst_ME_data_dir}/ME_Wm.dat ${tst_ME_data_dir}/PSP_Wm.lhe.gz ) add_test( NAME ME_Wm_virt COMMAND test_ME_generic ${tst_ME_data_dir}/config_w_ME.yml ${tst_ME_data_dir}/ME_Wm_virt.dat ${tst_ME_data_dir}/PSP_Wm.lhe.gz ) add_test( NAME ME_Z COMMAND test_ME_generic ${tst_ME_data_dir}/config_Z_ME.yml ${tst_ME_data_dir}/ME_Z.dat ${tst_ME_data_dir}/PSP_Z.lhe.gz ) add_test( NAME ME_Z_virt COMMAND test_ME_generic ${tst_ME_data_dir}/config_Z_ME.yml ${tst_ME_data_dir}/ME_Z_virt.dat ${tst_ME_data_dir}/PSP_Z.lhe.gz ) add_test( NAME ME_Z_uno COMMAND test_ME_generic ${tst_ME_data_dir}/config_Z_ME.yml ${tst_ME_data_dir}/ME_Z_uno_tree.dat ${tst_ME_data_dir}/PSP_Z_uno.lhe.gz ) add_test( NAME ME_Z_uno_virt COMMAND test_ME_generic ${tst_ME_data_dir}/config_Z_ME.yml ${tst_ME_data_dir}/ME_Z_uno_virt.dat ${tst_ME_data_dir}/PSP_Z_uno.lhe.gz ) add_test( NAME ME_WpWp COMMAND test_ME_generic ${tst_ME_data_dir}/config_ww_ME.yml ${tst_ME_data_dir}/ME_WpWp.dat ${tst_ME_data_dir}/PSP_WpWp.lhe.gz ) add_test( NAME ME_WpWp_virt COMMAND test_ME_generic ${tst_ME_data_dir}/config_ww_ME.yml ${tst_ME_data_dir}/ME_WpWp_virt.dat ${tst_ME_data_dir}/PSP_WpWp.lhe.gz ) add_test( NAME ME_WmWm COMMAND test_ME_generic ${tst_ME_data_dir}/config_ww_ME.yml ${tst_ME_data_dir}/ME_WmWm.dat ${tst_ME_data_dir}/PSP_WmWm.lhe.gz ) add_test( NAME ME_WmWm_virt COMMAND test_ME_generic ${tst_ME_data_dir}/config_ww_ME.yml ${tst_ME_data_dir}/ME_WmWm_virt.dat ${tst_ME_data_dir}/PSP_WmWm.lhe.gz ) # HEJ@NLO Virtuals add_test( NAME ME_WmWm_hejnlo COMMAND test_ME_generic ${tst_ME_data_dir}/config_ww_ME_hejnlo.yml ${tst_ME_data_dir}/ME_WmWm_virt_hejnlo.dat ${tst_ME_data_dir}/PSP_WmWm.lhe.gz ) add_test( NAME ME_WpWp_hejnlo COMMAND test_ME_generic ${tst_ME_data_dir}/config_ww_ME_hejnlo.yml ${tst_ME_data_dir}/ME_WpWp_virt_hejnlo.dat ${tst_ME_data_dir}/PSP_WpWp.lhe.gz ) add_test( NAME ME_Wp_hejnlo COMMAND test_ME_generic ${tst_ME_data_dir}/config_wzhpure_ME_hejnlo.yml ${tst_ME_data_dir}/ME_Wp_virt_hejnlo.dat ${tst_ME_data_dir}/PSP_Wp.lhe.gz ) add_test( NAME ME_Wm_hejnlo COMMAND test_ME_generic ${tst_ME_data_dir}/config_wzhpure_ME_hejnlo.yml ${tst_ME_data_dir}/ME_Wm_virt_hejnlo.dat ${tst_ME_data_dir}/PSP_Wm.lhe.gz ) add_test( NAME ME_Z_hejnlo COMMAND test_ME_generic ${tst_ME_data_dir}/config_wzhpure_ME_hejnlo.yml ${tst_ME_data_dir}/ME_Z_virt_hejnlo.dat ${tst_ME_data_dir}/PSP_Z.lhe.gz ) add_test( NAME ME_jets_hejnlo COMMAND test_ME_generic ${tst_ME_data_dir}/config_wzhpure_ME_hejnlo.yml ${tst_ME_data_dir}/ME_jets_virt_hejnlo.dat ${tst_ME_data_dir}/PSP_jets.lhe.gz ) add_test( NAME ME_h_hejnlo COMMAND test_ME_generic ${tst_ME_data_dir}/config_wzhpure_ME_hejnlo.yml ${tst_ME_data_dir}/ME_h_virt_hejnlo.dat ${tst_ME_data_dir}/PSP_h.lhe.gz ) add_test( NAME ME_j_log_corr COMMAND test_ME_generic ${tst_ME_data_dir}/config_log_corr.yml ${tst_ME_data_dir}/ME_jets_log_corr.dat ${tst_ME_data_dir}/PSP_jets.lhe.gz ) add_test( NAME ME_j_lambda COMMAND test_ME_generic ${tst_ME_data_dir}/config_lambda.yml ${tst_ME_data_dir}/ME_jets_lambda.dat ${tst_ME_data_dir}/PSP_jets.lhe.gz ) # test main executable file(COPY "${tst_dir}/jet_config.yml" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}") set(test_config "${CMAKE_CURRENT_BINARY_DIR}/jet_config.yml") if(HighFive_FOUND) file(READ ${test_config} config) file(WRITE ${test_config} "${config} - tst.hdf5\n") endif() if(HepMC3_FOUND) file(READ ${test_config} config) file(WRITE ${test_config} "${config} - tst.hepmc\n") endif() if(HepMC_FOUND) file(READ ${test_config} config) file(WRITE ${test_config} "${config} - tst.hepmc2\n") endif() if(rivet_FOUND) file(READ ${test_config} config) - file(WRITE ${test_config} "${config}\nanalysis:\n rivet: MC_XS\n output: tst\n") + file(WRITE ${test_config} "${config}\nanalyses:\n - rivet: MC_XS\n output: tst\n") endif() set(test_cmd_main "$\\\;${test_config}\\\;${tst_dir}/2j.lhe.gz") # check that HepMC3 output is correct if(HepMC3_FOUND) add_executable(check_hepmc ${tst_dir}/check_hepmc.cc) target_link_libraries(check_hepmc HEJ ${HEPMC3_LIBRARIES}) target_include_directories(check_hepmc PRIVATE ${HEPMC3_INCLUDE_DIR}) set(test_cmd_hepmc "$\\\;tst.hepmc") else() set(test_cmd_hepmc "") endif() if(HepMC_FOUND) add_executable(check_hepmc2 ${tst_dir}/check_hepmc2.cc) target_link_libraries(check_hepmc2 HEJ ${HepMC_LIBRARY}) target_include_directories(check_hepmc2 PRIVATE ${HepMC_INCLUDE_DIR}) endif() if(HighFive_FOUND) add_executable(check_highfive ${tst_dir}/check_highfive.cc) target_link_libraries(check_highfive HEJ HighFive) endif() # check that LHEF output is correct add_executable(check_lhe ${tst_dir}/check_lhe.cc) target_link_libraries(check_lhe HEJ hej_test) set(test_cmd_lhe "$\\\;tst.lhe") # check that rivet interface is consistent with naive rivet if(rivet_FOUND) # this assumes "rivet" and "yodadiff" are found in PATH if(rivet_USE_HEPMC3) set(hepmc_file "tst.hepmc") else() set(hepmc_file "tst.hepmc2") endif() if(rivet_USE_HEPMC3 OR (rivet_VERSION VERSION_LESS 3)) set(histo_exclude "") else() # rivet 3 with HepMC 2 is inconsistent in order of weights # -> interface != direct call (by permutation) # REQUIRES Yoda 1.7.5 set(histo_exclude "-M\\\;\\\\d") endif() set(test_cmd_rivet "rivet\\\;-a\\\;MC_XS\\\;${hepmc_file}\\\;-o\\\;tst_direct.yoda\ \;yodadiff\\\;${histo_exclude}\\\;tst.yoda\\\;tst_direct.yoda") else() set(test_cmd_rivet "") endif() # Run dependent tests in one command to ensure correct execution order # Note: The commands are concatenated with "\;" to escape CMake lists. # Thus arguments have to be escaped twice "\\\;". # e.g. "cmd1\;cmd2\\\;arg1\\\;arg2" is executed like "cmd1 && cmd2 arg1 arg2" add_test( NAME main COMMAND ${CMAKE_COMMAND} -DCMDS=${test_cmd_main}\;${test_cmd_hepmc}\;${test_cmd_lhe}\;${test_cmd_rivet} -P ${PROJECT_SOURCE_DIR}/cmake/run_multiple_tests.cmake ) add_test( NAME main_example COMMAND $ ${PROJECT_SOURCE_DIR}/config.yml ${tst_dir}/h_3j.lhe.gz ) # check that Sherpas LHE input can be read add_executable(check_lhe_sherpa ${tst_dir}/check_lhe_sherpa.cc) target_link_libraries(check_lhe_sherpa HEJ hej_test) add_test( NAME sherpa_reader COMMAND check_lhe_sherpa ${tst_dir}/SherpaLHE.lhe 1.62624e+08 ) # check HDF5 reader & writer if(HighFive_FOUND) add_executable(test_hdf5 ${tst_dir}/test_hdf5.cc) target_link_libraries(test_hdf5 HEJ) add_test( NAME hdf5_read COMMAND test_hdf5 ${tst_dir}/Wm9-g4-repack.hdf5 ) add_executable(test_hdf5_write ${tst_dir}/test_hdf5_write.cc) target_link_libraries(test_hdf5_write HEJ hej_test) add_test( NAME hdf5_write COMMAND test_hdf5_write ${tst_dir}/Wm9-g4-repack.hdf5 output.hdf5 ) endif() # check rivet interface if(RIVET_FOUND) add_executable(check_rivet ${tst_dir}/check_rivet.cc) target_link_libraries(check_rivet HEJ rivet::rivet) add_test( NAME rivet COMMAND check_rivet ) find_program (BASH_PROGRAM bash) if (BASH_PROGRAM) add_test( NAME fifo_test COMMAND ${BASH_PROGRAM} ${tst_dir}/fifotest.sh ${tst_dir}/2j.lhe.gz $) endif (BASH_PROGRAM) endif() # test boson reconstruction add_executable(cmp_events ${tst_dir}/cmp_events.cc) target_link_libraries(cmp_events HEJ) add_test( NAME reconstruct_W COMMAND cmp_events ${tst_dir}/epnu2jLOFKL_unweight.lhe.tar.gz ${tst_dir}/epnu2jLOFKL_unweight_noW.lhe.gz ) # test repairing slightly off-shell momenta add_executable(repair_off-shell ${tst_dir}/repair_off-shell.cc) target_link_libraries(repair_off-shell HEJ) add_test( NAME repair_off-shell COMMAND repair_off-shell ${tst_dir}/off-shell.lhe.gz ) # test resummed result add_executable(check_res ${tst_dir}/check_res.cc) target_link_libraries(check_res HEJ hej_test) # Setup yaml files for check res tests set(CENTRALSCALE 91.188) set(LOWPT_OPTION true) configure_file( ${tst_dir}/config_check_res.yml.in config_lowpt.yml @ONLY ) set(LOWPT_OPTION false) configure_file( ${tst_dir}/config_check_res.yml.in config_default.yml @ONLY ) set(CENTRALSCALE 125.) configure_file( ${tst_dir}/config_check_res.yml.in config_higgs.yml @ONLY ) # Check first event of HEJ output set(xstest_cmd_lhef "$\\\;${test_config}\\\;${tst_dir}/h_1j.lhe.gz") set(xstest_cmd_lhef_check "$\\\;tst.lhe\\\;28024.1") add_test( NAME test_lhe_xs COMMAND ${CMAKE_COMMAND} -DCMDS=${xstest_cmd_lhef}\;${xstest_cmd_lhef_check} -P ${PROJECT_SOURCE_DIR}/cmake/run_multiple_tests.cmake ) set_tests_properties(test_lhe_xs PROPERTIES DEPENDS "main") if(HepMC3_FOUND) set(xstest_cmd_hepmc "$\\\;${test_config}\\\;${tst_dir}/h_1j.lhe.gz") set(xstest_cmd_hepmc_check "$\\\;tst.hepmc\\\;28024.1") add_test( NAME test_hepmc_xs COMMAND ${CMAKE_COMMAND} -DCMDS=${xstest_cmd_hepmc}\;${xstest_cmd_hepmc_check} -P ${PROJECT_SOURCE_DIR}/cmake/run_multiple_tests.cmake ) - set_tests_properties(test_hepmc_xs PROPERTIES DEPENDS "main") + set_tests_properties(test_hepmc_xs PROPERTIES DEPENDS "main") set_tests_properties(test_hepmc_xs PROPERTIES RESOURCE_LOCK xstests) endif() if(HepMC_FOUND) set(xstest_cmd_hepmc2 "$\\\;${test_config}\\\;${tst_dir}/h_1j.lhe.gz") set(xstest_cmd_hepmc2_check "$\\\;tst.hepmc2\\\;28024.1") add_test( NAME test_hepmc2_xs COMMAND ${CMAKE_COMMAND} -DCMDS=${xstest_cmd_hepmc2}\;${xstest_cmd_hepmc2_check} -P ${PROJECT_SOURCE_DIR}/cmake/run_multiple_tests.cmake ) set_tests_properties(test_hepmc2_xs PROPERTIES DEPENDS "main") set_tests_properties(test_hepmc2_xs PROPERTIES RESOURCE_LOCK xstests) endif() if(HighFive_FOUND) set(xstest_cmd_highfive "$\\\;${test_config}\\\;${tst_dir}/h_1j.lhe.gz") set(xstest_cmd_highfive_check "$\\\;tst.hdf5\\\;28024.1") add_test( NAME xstest_highfive COMMAND ${CMAKE_COMMAND} -DCMDS=${xstest_cmd_highfive}\;${xstest_cmd_highfive_check} -P ${PROJECT_SOURCE_DIR}/cmake/run_multiple_tests.cmake ) set_tests_properties(xstest_highfive PROPERTIES DEPENDS "main;test_lhe_xs;") set_tests_properties(xstest_highfive PROPERTIES RESOURCE_LOCK xstests) endif() set_tests_properties(main test_lhe_xs PROPERTIES RESOURCE_LOCK xstests ) add_test( NAME xs_h_1j COMMAND check_res config_higgs.yml ${tst_dir}/h_1j.lhe.gz 4.97087 0.0302519 ) add_test( NAME xs_2j COMMAND check_res config_default.yml ${tst_dir}/2j.lhe.gz 3.49391e+07 419684 ) add_test( NAME xs_3j COMMAND check_res config_default.yml ${tst_dir}/3j.lhe.gz 2.37902e+06 25746.6 ) add_test( NAME xs_3j_unof COMMAND check_res config_default.yml ${tst_dir}/3j.lhe.gz 133399 4688.83 unof ) add_test( NAME xs_3j_unob COMMAND check_res config_default.yml ${tst_dir}/3j.lhe.gz 105247 3449.45 unob ) add_test( NAME xs_3j_splitf COMMAND check_res config_default.yml ${tst_dir}/3j.lhe.gz 97659.9 2748.65 splitf ) add_test( NAME xs_3j_splitb COMMAND check_res config_default.yml ${tst_dir}/3j.lhe.gz 107150 2799.8 splitb ) add_test( NAME xs_4j COMMAND check_res config_default.yml ${tst_dir}/4j.lhe.gz 603713 72822.6 ) add_test( NAME xs_4j_qqbar_mid COMMAND check_res config_default.yml ${tst_dir}/4j.lhe.gz 21866.7 1716.96 qqbar_mid ) add_test( NAME xs_h_3j COMMAND check_res config_higgs.yml ${tst_dir}/h_3j.lhe.gz 0.667678 0.0126859 ) add_test( NAME xs_h_3j_unof COMMAND check_res config_higgs.yml ${tst_dir}/h_3j_uno.lhe.gz 0.0110041 0.000274214 unof ) add_test( NAME xs_h_3j_unob COMMAND check_res config_higgs.yml ${tst_dir}/h_3j_uno.lhe.gz 0.0116516 0.000376737 unob ) add_test( NAME xs_epnu_3j COMMAND check_res config_default.yml ${tst_dir}/MGepnu3j_unweighted.lhe.gz 84394.7 3770.35 ) add_test( NAME xs_emnubar_3j COMMAND check_res config_default.yml ${tst_dir}/MGemnubar3j_unweighted.lhe.gz 53489.1 977.234 ) add_test( NAME xs_epnu_4j COMMAND check_res config_default.yml ${tst_dir}/MGepnu4j_unweighted.lhe.gz 19616.2 774.336 ) add_test( NAME xs_emnubar_4j COMMAND check_res config_default.yml ${tst_dir}/MGemnubar4j_unweighted.lhe.gz 10169.6 248.741 ) add_test( NAME xs_2j_lowpt COMMAND check_res config_lowpt.yml ${tst_dir}/2j.lhe.gz 45890.2 5325.62 ) if(TEST_ALL) # deactivate long tests by default add_test( NAME xs_h_1j_long COMMAND check_res config_higgs.yml ${tst_dir}/h_1j_large.lhe.gz 4.70112 0.00415353 ) add_test( NAME xs_epnu_2j COMMAND check_res config_default.yml ${tst_dir}/epnu2jLOFKL_unweight.lhe.tar.gz 262.7 3 ) add_test( NAME xs_epnu_3j_long COMMAND check_res config_default.yml ${tst_dir}/MGepnu3j_unweighted_large.lhe.gz 38.9512 1 ) add_test( NAME xs_emnubar_3j_long COMMAND check_res config_default.yml ${tst_dir}/MGemnubar3j_unweighted_large.lhe.gz 24.1575 1 ) add_test( NAME xs_epnu_3j_unof COMMAND check_res config_default.yml ${tst_dir}/MGepnu3j_unweighted_large.lhe.gz 9.63702 0.128355 unof ) add_test( NAME xs_epnu_3j_unob COMMAND check_res config_default.yml ${tst_dir}/MGepnu3j_unweighted_large.lhe.gz 9.70119 0.108436 unob ) add_test( NAME xs_epnu_3j_splitf COMMAND check_res config_default.yml ${tst_dir}/MGepnu3j_unweighted_large.lhe.gz 2.91995 0.0463182 splitf ) add_test( NAME xs_epnu_3j_splitb COMMAND check_res config_default.yml ${tst_dir}/MGepnu3j_unweighted_large.lhe.gz 3.40708 0.0550975 splitb ) add_test( NAME xs_epnu_4j_long COMMAND check_res config_default.yml ${tst_dir}/MGepnu4j_unweighted_large.lhe.gz 10.2542 0.135106 ) add_test( NAME xs_emnubar_4j_long COMMAND check_res config_default.yml ${tst_dir}/MGemnubar4j_unweighted_large.lhe.gz 5.73282 0.0583738 ) add_test( NAME xs_epnu_4j_qqbar_mid COMMAND check_res config_default.yml ${tst_dir}/MGepnu4j_unweighted_large.lhe.gz 0.802603 0.0126908 qqbar_mid ) endif() diff --git a/t/analysis_config_single.yml.in b/t/analysis_config_single.yml.in index 0c34b58..91dab93 100644 --- a/t/analysis_config_single.yml.in +++ b/t/analysis_config_single.yml.in @@ -1,43 +1,43 @@ trials: 10 resummation jets: min pt: 35 algorithm: antikt R: 0.4 fixed order jets: min pt: 30 event treatment: FKL: reweight unordered: discard extremal qqbar: reweight central qqbar: discard non-resummable: keep log correction: false scales: 125 random generator: name: mixmax seed: 11 vev: 246.2196508 particle properties: Higgs: mass: 125 width: 0.004165 W: mass: 80.385 width: 2.085 Z: mass: 91.187 width: 2.495 -analysis: - plugin: @ANALYSIS_PATH@/lib@ANALYSIS_LIB@.so -@ANALYSIS_PARAMETERS@ +analyses: + - plugin: @ANALYSIS_PATH@/lib@ANALYSIS_LIB@.so + @ANALYSIS_PARAMETERS@ max events: 100 diff --git a/t/fifotest.sh b/t/fifotest.sh index 47c4c64..a358964 100644 --- a/t/fifotest.sh +++ b/t/fifotest.sh @@ -1,27 +1,26 @@ # Script for running HEJ with FIFO set -eu FIFO=input.lhe.gz # Copy config file and change output file name cp analysis_config_simple.yml config_rivet.yml -sed -i "s/analysis/analyses/g" config_rivet.yml -sed -i "s/plugin:.*/ - rivet: MC_XS\n output: analysis_rivet/g" config_rivet.yml +sed -i "s/plugin:.*/ rivet: MC_XS\n output: analysis_rivet/g" config_rivet.yml # run fifo mkfifo $FIFO cat $1 >> $FIFO & $2 config_rivet.yml $FIFO rm $FIFO mv analysis_rivet.yoda analysis_fifo.yoda # run w/o fifo $2 config_rivet.yml $1 mv analysis_rivet.yoda analysis_nofifo.yoda # make sure fails #sed -i "s/YODA/GROGU/g" analysis_fifo.yoda #compare diff analysis_fifo.yoda analysis_nofifo.yoda