Page Menu
Home
HEPForge
Search
Configure Global Search
Log In
Files
F9501716
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
30 KB
Subscribers
None
View Options
diff --git a/FixedOrderGen/configFO.yml b/FixedOrderGen/configFO.yml
index fae8bab..6fca80b 100644
--- a/FixedOrderGen/configFO.yml
+++ b/FixedOrderGen/configFO.yml
@@ -1,97 +1,94 @@
## Number of generated events
events: 200
jets:
min pt: 20 # minimal jet pt, should be slightly below analysis cut
peak pt: 30 # peak pt of jets, should be at analysis cut
algorithm: antikt # jet clustering algorithm
R: 0.4 # jet R parameter
max rapidity: 5 # maximum jet rapidity
## Particle beam
beam:
energy: 6500
particles: [p, p]
## PDF ID according to LHAPDF
pdf: 230000
## Scattering process
process: p p => h 4j
## Particle decays (multiple decays are allowed)
decays:
Higgs: {into: [photon, photon], branching ratio: 0.0023568762400521404}
Wp: {into: [e+, nu_e], branching ratio: 1}
Wm: {into: [e-, nu_e_bar]} # equivalent to "branching ratio: 1"
## Fraction of events with two extremal emissions in one direction
## that contain an subleading emission e.g. unordered emission
subleading fraction: 0.05
## Allow different subleading configurations.
## By default all processes are allowed.
## This does not check if the processes are implemented in HEJ!
#
# subleading channels:
# - unordered
# - qqx
## Unweighting parameters
## remove to obtain weighted events
# unweight:
# sample size: 200 # should be similar to "events:", but not more than ~10000
# max deviation: 0
## --- The following settings are equivalent to HEJ, --- ##
## --- see HEJ for reference. --- ##
## Central scale choice
scales: max jet pperp
## Event output files
event output:
- HEJFO.lhe
# - HEJFO_events.hepmc
-## Analysis
-## Rivet analysis
-#
-# analysis:
-# rivet: MC_XS # rivet analysis name
-# output: HEJ # name of the yoda files, ".yoda" and scale suffix will be added
+## Analyses
#
+# analyses:
+## Rivet analysis
+# - rivet: MC_XS # rivet analysis name
+# output: HEJ # name of the yoda files, ".yoda" and scale suffix will be added
## Custom analysis
-#
-# analysis:
-# plugin: /path/to/libmyanalysis.so
-# my analysis parameter: some value
+# - plugin: /path/to/libmyanalysis.so
+# my analysis parameter: some value
## Selection of random number generator and seed
random generator:
name: mixmax
# seed: 1
## Vacuum expectation value
vev: 246.2196508
## Properties of the weak gauge bosons
particle properties:
Higgs:
mass: 125
width: 0.004165
W:
mass: 80.385
width: 2.085
Z:
mass: 91.187
width: 2.495
## Parameters for Higgs-gluon couplings
## this requires compilation with QCDloop
#
# Higgs coupling:
# use impact factors: false
# mt: 174
# include bottom: true
# mb: 4.7
diff --git a/FixedOrderGen/include/config.hh b/FixedOrderGen/include/config.hh
index 6dfff7b..461fcee 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;
size_t events;
JetParameters jets;
Beam beam;
int pdf_id;
double subleading_fraction;
unsigned int subleading_channels; //! < see HEJFOG::Subleading
ParticlesDecayMap particle_decays;
- YAML::Node analysis_parameters;
+ std::vector<YAML::Node> analyses_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/config.cc b/FixedOrderGen/src/config.cc
index e241857..675e1c1 100644
--- a/FixedOrderGen/src/config.cc
+++ b/FixedOrderGen/src/config.cc
@@ -1,427 +1,437 @@
/**
* \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"
+ "event output", "analyses", "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,
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<Decay> 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<Decay> 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<std::string>();
const auto id = HEJ::to_ParticleID(boson);
result.emplace(id, get_decays(node, entry, boson));
}
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.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 "+HEJ::name(*config.process.boson)+" is required"};
}
- set_from_yaml_if_defined(config.analysis_parameters, yaml, "analysis");
+ set_from_yaml_if_defined(config.analyses_parameters, yaml, "analyses");
+ if(yaml["analysis"]){
+ 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"]) 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 3451bdc..3c5f939 100644
--- a/FixedOrderGen/src/main.cc
+++ b/FixedOrderGen/src/main.cc
@@ -1,261 +1,277 @@
/**
* \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 <cstdint>
#include "LHEF/LHEF.h"
#include "yaml-cpp/yaml.h"
#include <boost/iterator/filter_iterator.hpp>
#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 "HEJ/Unweighter.hh"
#include "config.hh"
#include "EventGenerator.hh"
#include "PhaseSpacePoint.hh"
#include "Version.hh"
namespace{
constexpr auto banner =
" __ ___ __ ______ __ "
" __ \n / / / (_)___ _/ /_ / ____/___ "
" ___ _________ ___ __ / /__ / /______ \n "
" / /_/ / / __ `/ __ \\ / __/ / __ \\/ _ \\/ ___/ __ `/ / / / __ / / _"
" \\/ __/ ___/ \n / __ / / /_/ / / / / / /___/ /"
" / / __/ / / /_/ / /_/ / / /_/ / __/ /_(__ ) "
" \n /_/ /_/_/\\__, /_/ /_/ /_____/_/ /_/\\___/_/ \\__, /\\__, / \\___"
"_/\\___/\\__/____/ \n ____///__/ "
"__ ____ ///__//____/ ______ __ "
" \n / ____(_) _____ ____/ / / __ \\_________/ /__ _____ / "
"____/__ ____ ___ _________ _/ /_____ _____\n / /_ / / |/_/ _ \\/ __"
" / / / / / ___/ __ / _ \\/ ___/ / / __/ _ \\/ __ \\/ _ \\/ ___/ __ `/ "
"__/ __ \\/ ___/\n / __/ / /> </ __/ /_/ / / /_/ / / / /_/ / __/ / "
" / /_/ / __/ / / / __/ / / /_/ / /_/ /_/ / / \n /_/ /_/_/|_|\\___"
"/\\__,_/ \\____/_/ \\__,_/\\___/_/ \\____/\\___/_/ /_/\\___/_/ "
"\\__,_/\\__/\\____/_/ \n";
constexpr double invGeV2_to_pb = 389379292.;
}
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, LHEF::HEPRUP const & heprup
+std::vector<std::unique_ptr<HEJ::Analysis>> get_analyses(
+ std::vector<YAML::Node> const & parameters, LHEF::HEPRUP const & heprup
){
try{
- return HEJ::get_analysis(parameters, heprup);
+ return HEJ::get_analyses(parameters, heprup);
}
catch(std::exception const & exc){
std::cerr << "Failed to load analysis: " << exc.what() << '\n';
std::exit(EXIT_FAILURE);
}
}
template<class Iterator>
auto make_lowpt_filter(Iterator begin, Iterator end, HEJ::optional<double> peak_pt){
return boost::make_filter_iterator(
[peak_pt](HEJ::Event const & ev){
assert(! ev.jets().empty());
double min_pt = peak_pt?(*peak_pt):0.;
const auto softest_jet = fastjet::sorted_by_pt(ev.jets()).back();
return softest_jet.pt() > min_pt;
},
begin, end
);
}
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::shared_ptr<HEJ::RNG> 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.particle_decays,
config.Higgs_coupling,
config.ew_parameters,
ran
};
// prepare process information for output
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};
- std::unique_ptr<HEJ::Analysis> analysis = get_analysis(
- config.analysis_parameters, heprup
+ std::vector<std::unique_ptr<HEJ::Analysis>> analyses = get_analyses(
+ config.analyses_parameters, heprup
);
- assert(analysis != nullptr);
+ assert(analyses.empty() || analyses.front() != nullptr);
// warm-up phase to train unweighter
HEJ::optional<HEJ::Unweighter> unweighter{};
std::map<HEJFOG::Status, std::uint64_t> status_counter;
std::vector<HEJ::Event> events;
std::uint64_t trials = 0;
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)) {
+ if(generator.status() != HEJFOG::good) continue;
+ const bool pass_cuts = analyses.empty()?true:std::any_of(
+ begin(analyses), end(analyses),
+ [&ev](auto const & analysis) { return analysis->pass_cuts(*ev, *ev); }
+ );
+ if(pass_cuts) {
events.emplace_back(std::move(*ev));
++warmup_progress;
}
}
std::cout << std::endl;
unweighter = HEJ::Unweighter();
unweighter->set_cut_to_peakwt(
make_lowpt_filter(events.cbegin(), events.cend(), config.jets.peak_pt),
make_lowpt_filter(events.cend(), events.cend(), config.jets.peak_pt),
config.unweight->max_dev
);
std::vector<HEJ::Event> unweighted_events;
for(auto && ev: events) {
auto unweighted = unweighter->unweight(std::move(ev), *ran);
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";
} // end unweighting warm-up
// main generation loop
// event weight is wrong, need to divide by "total number of trials" afterwards
HEJ::ProgressBar<size_t> progress{std::cout, config.events};
progress.increment(events.size());
events.reserve(config.events);
for(; events.size() < 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(generator.status() != HEJFOG::good) continue;
+ const bool pass_cuts = analyses.empty()?true:std::any_of(
+ begin(analyses), end(analyses),
+ [&ev](auto const & analysis) { return analysis->pass_cuts(*ev, *ev); }
+ );
+ if(pass_cuts) {
if(unweighter) {
auto unweighted = unweighter->unweight(std::move(*ev), *ran);
if(! unweighted) continue;
ev = std::move(unweighted);
}
events.emplace_back(std::move(*ev));
++progress;
}
}
std::cout << std::endl;
// final run though events with correct weight
HEJ::CrossSectionAccumulator xs;
for(auto & ev: events){
ev.parameters() *= invGeV2_to_pb/trials;
- analysis->fill(ev, ev);
+ for(auto const & analysis: analyses) {
+ if(analysis->pass_cuts(ev, ev)) {
+ analysis->fill(ev, ev);
+ }
+ }
writer.write(ev);
xs.fill(ev);
}
- analysis->finalise();
+ for(auto const & analysis: analyses) {
+ analysis->finalise();
+ }
// Print final informations
const std::chrono::duration<double> run_time = (clock::now() - start_time);
std::cout << "\nTask Runtime: " << run_time.count() << " seconds for "
<< events.size() << " Events (" << events.size()/run_time.count()
<< " evts/s)\n" << std::endl;
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 << "%" << std::endl;
}
return EXIT_SUCCESS;
}
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Sun, Feb 23, 3:00 PM (46 m, 51 s)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
4476755
Default Alt Text
(30 KB)
Attached To
rHEJ HEJ
Event Timeline
Log In to Comment