Page MenuHomeHEPForge

No OneTemporary

diff --git a/include/HEJ/event_types.hh b/include/HEJ/event_types.hh
index b5d49c9..38fc496 100644
--- a/include/HEJ/event_types.hh
+++ b/include/HEJ/event_types.hh
@@ -1,108 +1,108 @@
/** \file
* \brief Define different types of events.
*
* \authors The HEJ collaboration (see AUTHORS for details)
- * \date 2019
+ * \date 2019-2020
* \copyright GPLv2 or later
*/
#pragma once
#include <string>
-#include "HEJ/utility.hh"
+#include "HEJ/exceptions.hh"
namespace HEJ {
//! Namespace for event types
namespace event_type {
//! Possible event types
enum EventType: size_t {
non_resummable = 0, //!< event configuration not covered by All Order resummation
bad_final_state = 1, //!< event with an unsupported final state
no_2_jets = 2, //!< event with less than two jets
FKL = 4, //!< FKL-type event
unordered_backward = 8, //!< event with unordered backward emission
unordered_forward = 16, //!< event with unordered forward emission
extremal_qqxb = 32, //!< event with a backward extremal qqbar
extremal_qqxf = 64, //!< event with a forward extremal qqbar
central_qqx = 128, //!< event with a central qqbar
unob = unordered_backward, //!< alias for unordered_backward
unof = unordered_forward, //!< alias for unordered_forward
qqxexb = extremal_qqxb, //!< alias for extremal_qqxb
qqxexf = extremal_qqxf, //!< alias for extremal_qqxf
qqxmid = central_qqx, //!< alias for central_qqx
first_type = non_resummable, //!< alias for non_resummable
last_type = central_qqx //!< alias for central_qqx
};
//! Event type names
/**
* For example, name(FKL) is the string "FKL"
*/
inline std::string name(EventType type) {
switch(type) {
case FKL:
return "FKL";
case unordered_backward:
return "unordered backward";
case unordered_forward:
return "unordered forward";
case extremal_qqxb:
return "extremal qqbar backward";
case extremal_qqxf:
return "extremal qqbar forward";
case central_qqx:
return "central qqbar";
case non_resummable:
return "non-resummable";
case no_2_jets:
return "no 2 jets";
case bad_final_state:
return "bad final state";
default:
throw std::logic_error{"Unreachable"};
}
}
//! Returns True for a HEJ \ref event_type::EventType "EventType"
inline
bool is_resummable(EventType type) {
switch(type) {
case FKL:
case unordered_backward:
case unordered_forward:
case extremal_qqxb:
case extremal_qqxf:
case central_qqx:
return true;
default:
return false;
}
}
//! Returns True for an unordered \ref event_type::EventType "EventType"
inline
bool is_uno(EventType type) {
return type == unordered_backward || type == unordered_forward;
}
//! Returns True for an extremal_qqx \ref event_type::EventType "EventType"
inline
bool is_ex_qqx(EventType type) {
return type == extremal_qqxb || type == extremal_qqxf;
}
//! Returns True for an central_qqx \ref event_type::EventType "EventType"
inline
bool is_mid_qqx(EventType type) {
return type == central_qqx;
}
//! Returns True for any qqx event \ref event_type::EventType "EventType"
inline
bool is_qqx(EventType type) {
return is_ex_qqx(type) || is_mid_qqx(type);
}
} // namespace event_type
} // namespace HEJ
diff --git a/include/HEJ/utility.hh b/include/HEJ/utility.hh
index 41e1d21..eff7a08 100644
--- a/include/HEJ/utility.hh
+++ b/include/HEJ/utility.hh
@@ -1,103 +1,86 @@
/**
* \file
* \brief Contains various utilities
*
* \authors The HEJ collaboration (see AUTHORS for details)
- * \date 2019
+ * \date 2019-2020
* \copyright GPLv2 or later
*/
#pragma once
#include <memory>
#include <string>
#include "boost/core/demangle.hpp"
#include "fastjet/PseudoJet.hh"
namespace HEJ{
- //! Create a std::unique_ptr to a T object
- /**
- * For non-array types this works like std::make_unique,
- * which is not available under C++11
- */
- template<class T, class... Args>
- std::unique_ptr<T> make_unique(Args&&... a){
- return std::unique_ptr<T>{new T{std::forward<Args>(a)...}};
- }
-
- //! Create an array containing the passed arguments
- template<typename T, typename... U>
- constexpr
- std::array<T, 1 + sizeof...(U)> make_array(T t, U&&... rest){
- return {{t, std::forward<U>(rest)...}};
- }
-
inline
std::string join(
std::string const & /* delim */
){
return "";
}
inline
std::string join(
std::string const & /* delim */, std::string const & str
){
return str;
}
//! Join strings with a delimiter
/**
* @param delim Delimiter to be put between consecutive strings
* @param first First string
* @param second Second string
* @param rest Remaining strings
*/
template<typename... Strings>
std::string join(
std::string const & delim,
std::string const & first, std::string const & second,
Strings&&... rest
){
return join(delim, first + delim + second, std::forward<Strings>(rest)...);
}
//! Return the name of the argument's type
template<typename T>
std::string type_string(T&&){
return boost::core::demangle(typeid(T).name());
}
//! Eliminate compiler warnings for unused variables
template<typename... T>
constexpr void ignore(T&&...) {}
//! Check whether two doubles are closer than ep > 0 to each other
inline
bool nearby_ep(double a, double b, double ep){
assert(ep > 0);
return std::abs(a-b) < ep;
}
//! Check whether all components of two PseudoJets are closer than ep to each other
inline
bool nearby_ep(
fastjet::PseudoJet const & pa, fastjet::PseudoJet const & pb,
double ep
){
assert(ep > 0);
for(size_t i = 0; i < 4; ++i){
if(!nearby_ep(pa[i], pb[i], ep)) return false;
}
return true;
}
inline
bool nearby(
fastjet::PseudoJet const & pa, fastjet::PseudoJet const & pb, double const norm = 1.
){
return nearby_ep(pa, pb, 1e-7*norm);
}
} // namespace HEJ
diff --git a/src/EmptyAnalysis.cc b/src/EmptyAnalysis.cc
index c6fd24d..e339dc4 100644
--- a/src/EmptyAnalysis.cc
+++ b/src/EmptyAnalysis.cc
@@ -1,68 +1,68 @@
/**
* \authors The HEJ collaboration (see AUTHORS for details)
- * \date 2019
+ * \date 2019-2020
* \copyright GPLv2 or later
*/
#include "HEJ/EmptyAnalysis.hh"
#include <string>
#include <vector>
#include "yaml-cpp/yaml.h"
#include "HEJ/exceptions.hh"
namespace HEJ{
namespace{
std::vector<std::string> param_as_strings(YAML::Node const & parameters){
using YAML::NodeType;
switch(parameters.Type()){
case NodeType::Null:
case NodeType::Undefined:
return {};
case NodeType::Scalar:
return {parameters.as<std::string>()};
case NodeType::Sequence: {
std::vector<std::string> param_strings;
for(auto && param: parameters){
param_strings.emplace_back(param.as<std::string>());
}
return param_strings;
}
case NodeType::Map: {
std::vector<std::string> param_strings;
for(auto && param: parameters){
param_strings.emplace_back(param.first.as<std::string>());
}
return param_strings;
}
default:;
}
throw std::logic_error{"unreachable"};
}
}
std::unique_ptr<Analysis> EmptyAnalysis::create(
YAML::Node const & parameters, LHEF::HEPRUP const &
){
const auto param_strings = param_as_strings(parameters);
if(! param_strings.empty()){
std::string error{"Unknown analysis parameter(s):"};
for(auto && p: param_strings) error += " " + p;
throw unknown_option{error};
}
- return std::unique_ptr<Analysis>{new EmptyAnalysis{}};
+ return std::make_unique<EmptyAnalysis>();
}
void EmptyAnalysis::fill(Event const &, Event const &){
// do nothing
}
bool EmptyAnalysis::pass_cuts(Event const &, Event const &){
return true;
}
void EmptyAnalysis::finalise(){
// do nothing
}
}
diff --git a/src/HDF5Writer.cc b/src/HDF5Writer.cc
index ec9640f..59b93c3 100644
--- a/src/HDF5Writer.cc
+++ b/src/HDF5Writer.cc
@@ -1,403 +1,404 @@
/**
* \authors The HEJ collaboration (see AUTHORS for details)
* \date 2019-2020
* \copyright GPLv2 or later
*/
#include "HEJ/HDF5Writer.hh"
#include <cassert>
#include "LHEF/LHEF.h"
#include "HEJ/ConfigFlags.hh"
#ifdef HEJ_BUILD_WITH_HDF5
#include <type_traits>
#include <iterator>
#include "HEJ/event_types.hh"
#include "HEJ/Event.hh"
#include "highfive/H5File.hpp"
namespace HEJ{
using HighFive::File;
using HighFive::DataSpace;
namespace{
constexpr std::size_t chunk_size = 1000;
constexpr unsigned compression_level = 3;
size_t to_index(event_type::EventType const type){
return type==0?0:floor(log2(type))+1;
}
template<typename T>
void write_dataset(HighFive::Group & group, std::string const & name, T val) {
using data_t = std::decay_t<T>;
group.createDataSet<data_t>(name, DataSpace::From(val)).write(val);
}
template<typename T>
void write_dataset(
HighFive::Group & group, std::string const & name,
std::vector<T> const & val
) {
using data_t = std::decay_t<T>;
group.createDataSet<data_t>(name, DataSpace::From(val)).write(val);
}
struct Cache {
explicit Cache(size_t capacity):
capacity{capacity}
{
nparticles.reserve(capacity);
start.reserve(capacity);
pid.reserve(capacity);
weight.reserve(capacity);
scale.reserve(capacity);
fscale.reserve(capacity);
rscale.reserve(capacity);
aqed.reserve(capacity);
aqcd.reserve(capacity);
trials.reserve(capacity);
npLO.reserve(capacity);
npNLO.reserve(capacity);
}
void fill(HEJ::Event ev) {
const auto hepeup = to_HEPEUP(ev, nullptr);
// HEJ event to get nice wrapper
const auto num_partons = std::distance(ev.cbegin_partons(),
ev.cend_partons());
assert(num_partons>0);
// Number of partons for LO matching, HEJ requires at least 2 partons
npLO.emplace_back(num_partons>1?num_partons-2:num_partons);
// Number of real emissions in NLO, HEJ is LO -> -1
npNLO.emplace_back(-1);
fill_event_params(hepeup);
fill_event_particles(hepeup);
}
void fill_event_params(LHEF::HEPEUP const & ev) {
nparticles.emplace_back(ev.NUP);
start.emplace_back(particle_pos);
pid.emplace_back(ev.IDPRUP);
weight.emplace_back(ev.XWGTUP);
scale.emplace_back(ev.SCALUP);
fscale.emplace_back(ev.scales.muf);
rscale.emplace_back(ev.scales.mur);
aqed.emplace_back(ev.AQEDUP);
aqcd.emplace_back(ev.AQCDUP);
// set first trial=1 for first event
// -> sum(trials) = 1 -> xs=sum(weights)/sum(trials) as in Sherpa
if(particle_pos == 0){
trials.emplace_back(1.);
} else {
trials.emplace_back(0.);
}
particle_pos += ev.NUP;
}
void fill_event_particles(LHEF::HEPEUP const & ev) {
id.insert(end(id), begin(ev.IDUP), end(ev.IDUP));
status.insert(end(status), begin(ev.ISTUP), end(ev.ISTUP));
lifetime.insert(end(lifetime), begin(ev.VTIMUP), end(ev.VTIMUP));
spin.insert(end(spin), begin(ev.SPINUP), end(ev.SPINUP));
for(int i = 0; i < ev.NUP; ++i) {
mother1.emplace_back(ev.MOTHUP[i].first);
mother2.emplace_back(ev.MOTHUP[i].second);
color1.emplace_back(ev.ICOLUP[i].first);
color2.emplace_back(ev.ICOLUP[i].second);
px.emplace_back(ev.PUP[i][0]);
py.emplace_back(ev.PUP[i][1]);
pz.emplace_back(ev.PUP[i][2]);
e.emplace_back(ev.PUP[i][3]);
m.emplace_back(ev.PUP[i][4]);
}
}
bool is_full() const {
return nparticles.size() >= capacity;
}
void clear() {
nparticles.clear();
start.clear();
pid.clear();
id.clear();
status.clear();
mother1.clear();
mother2.clear();
color1.clear();
color2.clear();
weight.clear();
scale.clear();
fscale.clear();
rscale.clear();
aqed.clear();
aqcd.clear();
trials.clear();
npLO.clear();
npNLO.clear();
px.clear();
py.clear();
pz.clear();
e.clear();
m.clear();
lifetime.clear();
spin.clear();
}
size_t capacity;
std::vector<int> nparticles, start, pid, id, status,
mother1, mother2, color1, color2, npLO, npNLO;
std::vector<double> weight, scale, fscale, rscale, aqed,
aqcd, trials, px, py, pz, e, m, lifetime, spin;
private:
size_t particle_pos = 0;
};
}
struct HDF5Writer::HDF5WriterImpl{
File file;
LHEF::HEPRUP heprup;
Cache cache{chunk_size};
size_t event_idx = 0;
size_t particle_idx = 0;
HDF5WriterImpl(std::string const & filename, LHEF::HEPRUP && hepr):
file{filename, File::ReadWrite | File::Create | File::Truncate},
heprup{std::move(hepr)}
{
// TODO: code duplication with Les Houches Writer
const int max_number_types = to_index(event_type::last_type)+1;
heprup.NPRUP = max_number_types;
// ids of event types
heprup.LPRUP.clear();
heprup.LPRUP.reserve(max_number_types);
heprup.LPRUP.emplace_back(0);
for(size_t i=event_type::first_type+1; i<=event_type::last_type; i*=2) {
heprup.LPRUP.emplace_back(i);
}
heprup.XSECUP = std::vector<double>(max_number_types, 0.);
heprup.XERRUP = std::vector<double>(max_number_types, 0.);
heprup.XMAXUP = std::vector<double>(max_number_types, 0.);
write_init();
create_event_group();
create_particle_group();
}
void write_init() {
auto init = file.createGroup("init");
write_dataset(init, "PDFgroupA" , heprup.PDFGUP.first);
write_dataset(init, "PDFgroupB" , heprup.PDFGUP.second);
write_dataset(init, "PDFsetA" , heprup.PDFSUP.first);
write_dataset(init, "PDFsetB" , heprup.PDFSUP.second);
write_dataset(init, "beamA" , heprup.IDBMUP.first);
write_dataset(init, "beamB" , heprup.IDBMUP.second);
write_dataset(init, "energyA" , heprup.EBMUP.first);
write_dataset(init, "energyB" , heprup.EBMUP.second);
write_dataset(init, "numProcesses" , heprup.NPRUP);
write_dataset(init, "weightingStrategy", heprup.IDWTUP);
auto proc_info = file.createGroup("procInfo");
write_dataset(proc_info, "procId", heprup.LPRUP);
}
static HighFive::DataSetCreateProps const & hdf5_chunk() {
static const auto props = [](){
HighFive::DataSetCreateProps props;
props.add(HighFive::Chunking({chunk_size}));
props.add(HighFive::Deflate(compression_level));
return props;
}();
return props;
}
void create_event_group() {
static const auto dim = DataSpace({0}, {DataSpace::UNLIMITED});
auto events = file.createGroup("event");
events.createDataSet<int>("nparticles", dim, hdf5_chunk());
events.createDataSet<int>("start", dim, hdf5_chunk());
events.createDataSet<int>("pid", dim, hdf5_chunk());
events.createDataSet<double>("weight", dim, hdf5_chunk());
events.createDataSet<double>("scale", dim, hdf5_chunk());
events.createDataSet<double>("fscale", dim, hdf5_chunk());
events.createDataSet<double>("rscale", dim, hdf5_chunk());
events.createDataSet<double>("aqed", dim, hdf5_chunk());
events.createDataSet<double>("aqcd", dim, hdf5_chunk());
events.createDataSet<double>("trials", dim, hdf5_chunk());
events.createDataSet<int>("npLO", dim, hdf5_chunk());
events.createDataSet<int>("npNLO", dim, hdf5_chunk());
}
void resize_event_group(size_t new_size) {
auto events = file.getGroup("event");
events.getDataSet("nparticles").resize({new_size});
events.getDataSet("start").resize({new_size});
events.getDataSet("pid").resize({new_size});
events.getDataSet("weight").resize({new_size});
events.getDataSet("scale").resize({new_size});
events.getDataSet("fscale").resize({new_size});
events.getDataSet("rscale").resize({new_size});
events.getDataSet("aqed").resize({new_size});
events.getDataSet("aqcd").resize({new_size});
events.getDataSet("trials").resize({new_size});
events.getDataSet("npLO").resize({new_size});
events.getDataSet("npNLO").resize({new_size});
}
void create_particle_group() {
static const auto dim = DataSpace({0}, {DataSpace::UNLIMITED});
auto particles = file.createGroup("particle");
particles.createDataSet<int>("id", dim, hdf5_chunk());
particles.createDataSet<int>("status", dim, hdf5_chunk());
particles.createDataSet<int>("mother1", dim, hdf5_chunk());
particles.createDataSet<int>("mother2", dim, hdf5_chunk());
particles.createDataSet<int>("color1", dim, hdf5_chunk());
particles.createDataSet<int>("color2", dim, hdf5_chunk());
particles.createDataSet<double>("px", dim, hdf5_chunk());
particles.createDataSet<double>("py", dim, hdf5_chunk());
particles.createDataSet<double>("pz", dim, hdf5_chunk());
particles.createDataSet<double>("e", dim, hdf5_chunk());
particles.createDataSet<double>("m", dim, hdf5_chunk());
particles.createDataSet<double>("lifetime", dim, hdf5_chunk());
particles.createDataSet<double>("spin", dim, hdf5_chunk());
}
void resize_particle_group(size_t new_size) {
auto particles = file.getGroup("particle");
particles.getDataSet("id").resize({new_size});
particles.getDataSet("status").resize({new_size});
particles.getDataSet("mother1").resize({new_size});
particles.getDataSet("mother2").resize({new_size});
particles.getDataSet("color1").resize({new_size});
particles.getDataSet("color2").resize({new_size});
particles.getDataSet("px").resize({new_size});
particles.getDataSet("py").resize({new_size});
particles.getDataSet("pz").resize({new_size});
particles.getDataSet("e").resize({new_size});
particles.getDataSet("m").resize({new_size});
particles.getDataSet("lifetime").resize({new_size});
particles.getDataSet("spin").resize({new_size});
}
void write(Event const & ev){
cache.fill(ev);
if(cache.is_full()) {
dump_cache();
}
const double wt = ev.central().weight;
const size_t idx = to_index(ev.type());
heprup.XSECUP[idx] += wt;
heprup.XERRUP[idx] += wt*wt;
if(wt > heprup.XMAXUP[idx]){
heprup.XMAXUP[idx] = wt;
}
}
void dump_cache() {
write_event_params();
write_event_particles();
cache.clear();
}
void write_event_params() {
auto events = file.getGroup("event");
// choose arbitrary dataset to find size
const auto dataset = events.getDataSet("nparticles");
const size_t size = dataset.getSpace().getDimensions().front();
resize_event_group(size + cache.nparticles.size());
#define WRITE_FROM_CACHE(GROUP, PROPERTY) \
GROUP.getDataSet(#PROPERTY).select({size}, {cache.PROPERTY.size()}).write(cache.PROPERTY)
WRITE_FROM_CACHE(events, nparticles);
WRITE_FROM_CACHE(events, start);
WRITE_FROM_CACHE(events, pid);
WRITE_FROM_CACHE(events, weight);
WRITE_FROM_CACHE(events, scale);
WRITE_FROM_CACHE(events, fscale);
WRITE_FROM_CACHE(events, rscale);
WRITE_FROM_CACHE(events, aqed);
WRITE_FROM_CACHE(events, aqcd);
WRITE_FROM_CACHE(events, trials);
WRITE_FROM_CACHE(events, npLO);
WRITE_FROM_CACHE(events, npNLO);
}
void write_event_particles() {
auto particles = file.getGroup("particle");
// choose arbitrary dataset to find size
const auto dataset = particles.getDataSet("id");
const size_t size = dataset.getSpace().getDimensions().front();
resize_particle_group(size + cache.id.size());
WRITE_FROM_CACHE(particles, id);
WRITE_FROM_CACHE(particles, status);
WRITE_FROM_CACHE(particles, lifetime);
WRITE_FROM_CACHE(particles, spin);
WRITE_FROM_CACHE(particles, mother1);
WRITE_FROM_CACHE(particles, mother2);
WRITE_FROM_CACHE(particles, color1);
WRITE_FROM_CACHE(particles, color2);
WRITE_FROM_CACHE(particles, px);
WRITE_FROM_CACHE(particles, py);
WRITE_FROM_CACHE(particles, pz);
WRITE_FROM_CACHE(particles, e);
WRITE_FROM_CACHE(particles, m);
}
#undef WRITE_FROM_CACHE
~HDF5WriterImpl(){
dump_cache();
auto proc_info = file.getGroup("procInfo");
write_dataset(proc_info, "xSection", heprup.XSECUP);
write_dataset(proc_info, "error", heprup.XERRUP);
write_dataset(proc_info, "unitWeight", heprup.XMAXUP);
}
};
HDF5Writer::HDF5Writer(std::string const & filename, LHEF::HEPRUP heprup):
- impl_{new HDF5Writer::HDF5WriterImpl{filename, std::move(heprup)}}
+ impl_{std::make_unique<HDF5Writer::HDF5WriterImpl>(
+ filename, std::move(heprup))}
{}
void HDF5Writer::write(Event const & ev){
impl_->write(ev);
}
}
#else // no HDF5 support
namespace HEJ{
class HDF5Writer::HDF5WriterImpl{};
HDF5Writer::HDF5Writer(std::string const &, LHEF::HEPRUP){
throw std::invalid_argument{
"Failed to create HDF5 writer: "
"HEJ 2 was built without HDF5 support"
};
}
void HDF5Writer::write(Event const &){
assert(false);
}
}
#endif
namespace HEJ {
HDF5Writer::~HDF5Writer() = default;
}
diff --git a/src/HepMC2Writer.cc b/src/HepMC2Writer.cc
index 78824d3..4e21411 100644
--- a/src/HepMC2Writer.cc
+++ b/src/HepMC2Writer.cc
@@ -1,82 +1,82 @@
/**
* \authors The HEJ collaboration (see AUTHORS for details)
* \date 2019-2020
* \copyright GPLv2 or later
*/
#include "HEJ/HepMC2Writer.hh"
#include <cassert>
#include "LHEF/LHEF.h"
#include "HEJ/ConfigFlags.hh"
#ifdef HEJ_BUILD_WITH_HepMC2
#include "HepMC/IO_GenEvent.h"
#include <utility>
#include "HepMC/GenParticle.h"
#include "HepMC/GenVertex.h"
#include "HEJ/Event.hh"
#include "HEJ/exceptions.hh"
#include "HEJ/HepMC2Interface.hh"
namespace HEJ{
struct HepMC2Writer::HepMC2WriterImpl{
HepMC2Interface hepmc_;
HepMC2WriterImpl & operator=(HepMC2WriterImpl const & other) = delete;
HepMC2WriterImpl(HepMC2WriterImpl const & other) = delete;
HepMC2WriterImpl & operator=(HepMC2WriterImpl && other) = delete;
HepMC2WriterImpl(HepMC2WriterImpl && other) = delete;
HepMC::IO_GenEvent writer_;
HepMC2WriterImpl(
std::string const & file, LHEF::HEPRUP && heprup
):
hepmc_(heprup),
writer_{file}
{}
void write(Event const & ev){
auto out_ev = hepmc_(ev);
writer_.write_event(&out_ev);
}
};
HepMC2Writer::HepMC2Writer(std::string const & file, LHEF::HEPRUP heprup):
- impl_{new HepMC2WriterImpl{file, std::move(heprup)}}
+ impl_{std::make_unique<HepMC2WriterImpl>(file, std::move(heprup))}
{}
void HepMC2Writer::write(Event const & ev){
impl_->write(ev);
}
} // namespace HEJ
#else // no HepMC2
namespace HEJ{
class HepMC2Writer::HepMC2WriterImpl{};
HepMC2Writer::HepMC2Writer(std::string const &, LHEF::HEPRUP){
throw std::invalid_argument(
"Failed to create HepMC writer: "
"HEJ 2 was built without HepMC2 support"
);
}
void HepMC2Writer::write(Event const &){
assert(false);
}
}
#endif
namespace HEJ{
HepMC2Writer::~HepMC2Writer() = default;
}
diff --git a/src/LesHouchesWriter.cc b/src/LesHouchesWriter.cc
index 51ea535..46264c3 100644
--- a/src/LesHouchesWriter.cc
+++ b/src/LesHouchesWriter.cc
@@ -1,127 +1,122 @@
/**
* \authors The HEJ collaboration (see AUTHORS for details)
* \date 2019-2020
* \copyright GPLv2 or later
*/
#include <cassert>
#include <utility>
#include <vector>
#include "HEJ/Event.hh"
#include "HEJ/event_types.hh"
#include "HEJ/LesHouchesWriter.hh"
#include "HEJ/utility.hh"
namespace HEJ{
namespace{
- template<class T, class... Args>
- std::unique_ptr<T> make_unique(Args&&... a){
- return std::unique_ptr<T>{new T{std::forward<Args>(a)...}};
- }
-
size_t to_index(event_type::EventType const type){
return type==0?0:floor(log2(type))+1;
}
}
LesHouchesWriter::LesHouchesWriter(
std::string const & file, LHEF::HEPRUP heprup
):
out_{file, std::fstream::in | std::fstream::out | std::fstream::trunc},
- writer_{HEJ::make_unique<LHEF::Writer>(out_)}
+ writer_{std::make_unique<LHEF::Writer>(out_)}
{
if(! out_.is_open()){
throw std::ios_base::failure("Failed to open " + file);
};
// scientific style is needed to allow rewriting the init block
out_ << std::scientific;
writer_->heprup = std::move(heprup);
// lhe Standard: IDWTUP (negative => weights = +/-)
// IDWTUP: HEJ -> SHG/Pythia/next program
// 1: weighted->unweighted, xs = mean(weight), XMAXUP given
// 2: weighted->unweighted, xs = XSECUP, XMAXUP given
// 3: unweighted (weight=+1)->unweighted, no additional information
// 4: weighted->weighted, xs = mean(weight)
//
// None of these codes actually match what we want:
// 1 and 4 require xs = mean(weight), which is impossible until after generation
// 2 tells the SHG to unweight our events, which is wasteful
// 3 claims we produce unweighted events, which is both wasteful _and_
// impossible until after generation (we don't know the maximum weight before)
//
// For the time being, we choose -3. If the consumer (like Pythia) assumes
// weight=+1, the final weights have to be corrected by multiplying with
// the original weight we provided. We are also often use NLO-PDFs which can
// give negative weights, hence the native IDWTUP.
//
writer_->heprup.IDWTUP = -3;
// always use the newest LHE version
// Pythia only saves weights (hepeup.XWGTUP) for version >=2
writer_->heprup.version = LHEF::HEPRUP().version;
const int max_number_types = to_index(event_type::last_type)+1;
writer_->heprup.NPRUP = max_number_types;
// ids of event types
writer_->heprup.LPRUP.clear();
writer_->heprup.LPRUP.reserve(max_number_types);
writer_->heprup.LPRUP.emplace_back(0);
for(size_t i=event_type::first_type+1; i<=event_type::last_type; i*=2)
writer_->heprup.LPRUP.emplace_back(i);
// use placeholders for unknown init block values
// we can overwrite them after processing all events
writer_->heprup.XSECUP = std::vector<double>(max_number_types, 0.);
writer_->heprup.XERRUP = std::vector<double>(max_number_types, 0.);
writer_->heprup.XMAXUP = std::vector<double>(max_number_types, 0.);
write_init();
}
void LesHouchesWriter::write(Event const & ev){
assert(writer_ && out_.is_open());
const double wt = ev.central().weight;
writer_->hepeup = HEJ::to_HEPEUP(std::move(ev), &heprup());
writer_->writeEvent();
assert(heprup().XSECUP.size() > to_index(ev.type()));
heprup().XSECUP[to_index(ev.type())] += wt;
heprup().XERRUP[to_index(ev.type())] += wt*wt;
if(wt > heprup().XMAXUP[to_index(ev.type())]){
heprup().XMAXUP[to_index(ev.type())] = wt;
}
}
// this function is called after overwritting the Les Houches init block
// assert that we have overwritten *exactly* the init block,
// i.e. we are at the end of the file or an intact event block is next
void assert_next_event_intact(std::istream & out){
(void) out; // suppress compiler warnings if not in debug mode
#ifndef NDEBUG
std::string line;
getline(out, line);
assert(out.eof() || line.rfind("<event", 0) == 0);
#endif
}
void LesHouchesWriter::rewrite_init(){
assert(writer_ && out_.is_open());
// replace placeholder entries
const auto pos = out_.tellp();
out_.seekp(0);
write_init();
assert_next_event_intact(out_);
out_.seekp(pos);
}
LesHouchesWriter::~LesHouchesWriter(){
assert(writer_ && out_.is_open());
for(auto & xs_err: heprup().XERRUP)
{
xs_err = sqrt(xs_err);
}
rewrite_init();
}
}
diff --git a/src/make_writer.cc b/src/make_writer.cc
index 10a71b0..707bf74 100644
--- a/src/make_writer.cc
+++ b/src/make_writer.cc
@@ -1,41 +1,33 @@
/**
* \authors The HEJ collaboration (see AUTHORS for details)
- * \date 2019
+ * \date 2019-2020
* \copyright GPLv2 or later
*/
#include "HEJ/make_writer.hh"
#include "HEJ/exceptions.hh"
#include "HEJ/HepMC2Writer.hh"
#include "HEJ/HepMC3Writer.hh"
#include "HEJ/HDF5Writer.hh"
#include "HEJ/LesHouchesWriter.hh"
namespace HEJ{
std::unique_ptr<EventWriter> make_format_writer(
FileFormat format, std::string const & outfile,
LHEF::HEPRUP const & heprup
){
switch(format){
case FileFormat::Les_Houches:
- return std::unique_ptr<EventWriter>{
- new LesHouchesWriter{outfile, heprup}
- };
+ return std::make_unique<LesHouchesWriter>(outfile, heprup);
case FileFormat::HepMC2:
- return std::unique_ptr<EventWriter>{
- new HepMC2Writer{outfile, heprup}
- };
+ return std::make_unique<HepMC2Writer>(outfile, heprup);
case FileFormat::HepMC3:
- return std::unique_ptr<EventWriter>{
- new HepMC3Writer{outfile, heprup}
- };
+ return std::make_unique<HepMC3Writer>(outfile, heprup);
case FileFormat::HDF5:
- return std::unique_ptr<EventWriter>{
- new HDF5Writer{outfile, heprup}
- };
+ return std::make_unique<HDF5Writer>(outfile, heprup);
default:
throw std::logic_error("unhandled file format");
}
}
}
diff --git a/src/stream.cc b/src/stream.cc
index c4843eb..e1b9ad6 100644
--- a/src/stream.cc
+++ b/src/stream.cc
@@ -1,32 +1,32 @@
/**
* \authors The HEJ collaboration (see AUTHORS for details)
- * \date 2019
+ * \date 2019-2020
* \copyright GPLv2 or later
*/
#include "HEJ/stream.hh"
#include <boost/iostreams/filter/gzip.hpp>
namespace HEJ{
namespace{
bool is_gzip(std::ifstream & file){
static constexpr char magic_bytes[] = {'\x1f', '\x8b'};
if(file.peek() != magic_bytes[0]) return false;
file.get();
const char second = file.peek();
file.unget();
return second == magic_bytes[1];
}
}
istream::istream(std::string const & filename):
file_{filename, std::ios_base::in | std::ios_base::binary},
- stream_{new boost_istream()}
+ stream_{std::make_unique<boost_istream>()}
{
if(is_gzip(file_)){
stream_->push(boost::iostreams::gzip_decompressor{});
}
stream_->push(file_);
}
}
diff --git a/t/cmp_events.cc b/t/cmp_events.cc
index 0a3c833..0d51e2e 100644
--- a/t/cmp_events.cc
+++ b/t/cmp_events.cc
@@ -1,53 +1,59 @@
-#include "HEJ/stream.hh"
+/**
+ * \authors The HEJ collaboration (see AUTHORS for details)
+ * \date 2019-2020
+ * \copyright GPLv2 or later
+ */
#include "HEJ/Event.hh"
+#include "HEJ/stream.hh"
+#include "HEJ/utility.hh"
#include "LHEF/LHEF.h"
int main(int argn, char** argv) {
if(argn != 3){
std::cerr << "Usage: cmp_events eventfile eventfile_no_boson ";
return EXIT_FAILURE;
}
HEJ::istream in{argv[1]};
LHEF::Reader reader{in};
HEJ::istream in_no_boson{argv[2]};
LHEF::Reader reader_no_boson{in_no_boson};
while(reader.readEvent()) {
if(! reader_no_boson.readEvent()) {
std::cerr << "wrong number of events in " << argv[2] << '\n';
return EXIT_FAILURE;
}
const auto is_AWZH = [](HEJ::Particle const & p) {
return is_AWZH_boson(p);
};
const HEJ::Event::EventData event_data{reader.hepeup};
const auto boson = std::find_if(
begin(event_data.outgoing), end(event_data.outgoing), is_AWZH
);
if(boson == end(event_data.outgoing)) {
std::cerr << "no boson in event\n";
return EXIT_FAILURE;
}
HEJ::Event::EventData data_no_boson{reader_no_boson.hepeup};
data_no_boson.reconstruct_intermediate();
const auto new_boson = std::find_if(
begin(event_data.outgoing), end(event_data.outgoing), is_AWZH
);
if(new_boson == end(data_no_boson.outgoing)) {
std::cerr << "failed to find reconstructed boson\n";
return EXIT_FAILURE;
}
if(new_boson->type != boson->type) {
std::cerr << "reconstructed wrong boson type\n";
return EXIT_FAILURE;
}
if(!HEJ::nearby(new_boson->p, boson->p)) {
std::cerr << "reconstructed boson momentum is off\n";
return EXIT_FAILURE;
}
}
return EXIT_SUCCESS;
}
diff --git a/t/hej_test.cc b/t/hej_test.cc
index 145947c..92444f0 100644
--- a/t/hej_test.cc
+++ b/t/hej_test.cc
@@ -1,518 +1,523 @@
+/**
+ * \authors The HEJ collaboration (see AUTHORS for details)
+ * \date 2019-2020
+ * \copyright GPLv2 or later
+ */
#include "hej_test.hh"
#include <random>
HEJ::Event::EventData get_process(int const njet, int const pos_boson){
using namespace HEJ::pid;
HEJ::Event::EventData ev;
if(njet == 0){ // jet idx: -1 -1
ev.outgoing.push_back({gluon, { -24, 12, -57, 63}, {}});
ev.outgoing.push_back({gluon, { 24, -12, 41, 49}, {}});
ev.incoming[0] = {gluon, { 0, 0, -64, 64}, {}};
ev.incoming[1] = {gluon, { 0, 0, 48, 48}, {}};
return ev;
}
else if(njet == 1){ // jet idx: 0 -1 -1
ev.outgoing.push_back({gluon, { 23, 28, -44, 57}, {}});
ev.outgoing.push_back({gluon, { -11, -24, -12, 29}, {}});
ev.outgoing.push_back({gluon, { -12, -4, 39, 41}, {}});
ev.incoming[0] = {gluon, { 0, 0, -72, 72}, {}};
ev.incoming[1] = {gluon, { 0, 0, 55, 55}, {}};
return ev;
}
else if(njet == 2){
switch(pos_boson){
case 0:
ev.outgoing.push_back({higgs, { 198, 33, -170, 291}, {}});
ev.outgoing.push_back({gluon, {-154, 68, 44, 174}, {}});
ev.outgoing.push_back({gluon, { -44, -101, 88, 141}, {}});
ev.incoming[0] = {gluon, { 0, 0, -322, 322}, {}};
ev.incoming[1] = {gluon, { 0, 0, 284, 284}, {}};
return ev;
case 1:
ev.outgoing.push_back({gluon, { -6, 82, -159, 179}, {}});
ev.outgoing.push_back({higgs, { 195, -106, 74, 265}, {}});
ev.outgoing.push_back({gluon, {-189, 24, 108, 219}, {}});
ev.incoming[0] = {gluon, { 0, 0, -320, 320}, {}};
ev.incoming[1] = {gluon, { 0, 0, 343, 343}, {}};
return ev;
case 2:
ev.outgoing.push_back({gluon, { -80, -80, -140, 180}, {}});
ev.outgoing.push_back({gluon, { -60, -32, 0, 68}, {}});
ev.outgoing.push_back({higgs, { 140, 112, 177, 281}, {}});
ev.incoming[0] = {gluon, { 0, 0, -246, 246}, {}};
ev.incoming[1] = {gluon, { 0, 0, 283, 283}, {}};
return ev;
default:
ev.outgoing.push_back({gluon, { -72, 24, 18, 78}, {}});
ev.outgoing.push_back({gluon, { 72, -24, 74, 106}, {}});
ev.incoming[0] = {gluon, { 0, 0, -46, 46}, {}};
ev.incoming[1] = {gluon, { 0, 0, 138, 138}, {}};
return ev;
}
}
if(njet == 3){
switch(pos_boson){
case 0:
ev.outgoing.push_back({higgs, { 152, -117, -88, 245}, {}});
ev.outgoing.push_back({gluon, {-146, 62, -11, 159}, {}});
ev.outgoing.push_back({gluon, { 126, -72, 96, 174}, {}});
ev.outgoing.push_back({gluon, {-132, 127, 144, 233}, {}});
ev.incoming[0] = {gluon, { 0, 0, -335, 335}, {}};
ev.incoming[1] = {gluon, { 0, 0, 476, 476}, {}};
return ev;
case 1:
ev.outgoing.push_back({gluon, {-191, 188, -128, 297}, {}});
ev.outgoing.push_back({higgs, { 199, 72, -76, 257}, {}});
ev.outgoing.push_back({gluon, { 184, -172, -8, 252}, {}});
ev.outgoing.push_back({gluon, {-192, -88, 54, 218}, {}});
ev.incoming[0] = {gluon, { 0, 0, -591, 591}, {}};
ev.incoming[1] = {gluon, { 0, 0, 433, 433}, {}};
return ev;
case 2:
ev.outgoing.push_back({gluon, { -42, 18, -49, 67}, {}});
ev.outgoing.push_back({gluon, { -12, -54, -28, 62}, {}});
ev.outgoing.push_back({higgs, { 99, 32, -16, 163}, {}});
ev.outgoing.push_back({gluon, { -45, 4, 72, 85}, {}});
ev.incoming[0] = {gluon, { 0, 0, -199, 199}, {}};
ev.incoming[1] = {gluon, { 0, 0, 178, 178}, {}};
return ev;
case 3:
ev.outgoing.push_back({gluon, { -65, -32, -76, 105}, {}});
ev.outgoing.push_back({gluon, { -22, 31, -34, 51}, {}});
ev.outgoing.push_back({gluon, { -12, -67, -36, 77}, {}});
ev.outgoing.push_back({higgs, { 99, 68, -4, 173}, {}});
ev.incoming[0] = {gluon, { 0, 0, -278, 278}, {}};
ev.incoming[1] = {gluon, { 0, 0, 128, 128}, {}};
return ev;
default:
ev.outgoing.push_back({gluon, { -90, -135, 30, 165}, {}});
ev.outgoing.push_back({gluon, {-108, 198, 76, 238}, {}});
ev.outgoing.push_back({gluon, { 198, -63, 126, 243}, {}});
ev.incoming[0] = {gluon, { 0, 0, -207, 207}, {}};
ev.incoming[1] = {gluon, { 0, 0, 439, 439}, {}};
return ev;
}
}
if(njet == 4){
switch(pos_boson){
case 0:
ev.outgoing.push_back({higgs, { 199, 72, -76, 257}, {}});
ev.outgoing.push_back({gluon, {-200, -155, -64, 261}, {}});
ev.outgoing.push_back({gluon, { 198, 194, 57, 283}, {}});
ev.outgoing.push_back({gluon, { 1, 32, 8, 33}, {}});
ev.outgoing.push_back({gluon, {-198, -143, 186, 307}, {}});
ev.incoming[0] = {gluon, { 0, 0, -515, 515}, {}};
ev.incoming[1] = {gluon, { 0, 0, 626, 626}, {}};
return ev;
case 1:
ev.outgoing.push_back({gluon, { 198, 61, -162, 263}, {}});
ev.outgoing.push_back({higgs, { 199, 72, -76, 257}, {}});
ev.outgoing.push_back({gluon, {-200, 135, 144, 281}, {}});
ev.outgoing.push_back({gluon, {-198, -186, 171, 321}, {}});
ev.outgoing.push_back({gluon, { 1, -82, 122, 147}, {}});
ev.incoming[0] = {gluon, { 0, 0, -535, 535}, {}};
ev.incoming[1] = {gluon, { 0, 0, 734, 734}, {}};
return ev;
case 2:
ev.outgoing.push_back({gluon, {-180, -27, -164, 245}, {}});
ev.outgoing.push_back({gluon, {-108, 78, -36, 138}, {}});
ev.outgoing.push_back({higgs, { 196, -189, 68, 307}, {}});
ev.outgoing.push_back({gluon, {-107, 136, 76, 189}, {}});
ev.outgoing.push_back({gluon, { 199, 2, 178, 267}, {}});
ev.incoming[0] = {gluon, { 0, 0, -512, 512}, {}};
ev.incoming[1] = {gluon, { 0, 0, 634, 634}, {}};
return ev;
case 3:
ev.outgoing.push_back({gluon, { -12, -30, -84, 90}, {}});
ev.outgoing.push_back({gluon, { -72, 22, -96, 122}, {}});
ev.outgoing.push_back({gluon, { 68, 0, -51, 85}, {}});
ev.outgoing.push_back({higgs, { 64, 72, -81, 177}, {}});
ev.outgoing.push_back({gluon, { -48, -64, 84, 116}, {}});
ev.incoming[0] = {gluon, { 0, 0, -409, 409}, {}};
ev.incoming[1] = {gluon, { 0, 0, 181, 181}, {}};
return ev;
case 4:
ev.outgoing.push_back({gluon, { -72, -49, -72, 113}, {}});
ev.outgoing.push_back({gluon, { -48, 0, -36, 60}, {}});
ev.outgoing.push_back({gluon, { -12, 54, -36, 66}, {}});
ev.outgoing.push_back({gluon, { 68, -77, -56, 117}, {}});
ev.outgoing.push_back({higgs, { 64, 72, -81, 177}, {}});
ev.incoming[0] = {gluon, { 0, 0, -407, 407}, {}};
ev.incoming[1] = {gluon, { 0, 0, 126, 126}, {}};
return ev;
default:
ev.outgoing.push_back({gluon, { 248, -56, -122, 282}, {}});
ev.outgoing.push_back({gluon, { 249, 30, -10, 251}, {}});
ev.outgoing.push_back({gluon, {-249, -18, 26, 251}, {}});
ev.outgoing.push_back({gluon, {-248, 44, 199, 321}, {}});
ev.incoming[0] = {gluon, { 0, 0, -506, 506}, {}};
ev.incoming[1] = {gluon, { 0, 0, 599, 599}, {}};
return ev;
}
}
if(njet == 6){
switch(pos_boson){
case 0:
ev.outgoing.push_back({higgs, { 349, 330, -94, 505}, {}});
ev.outgoing.push_back({gluon, {-315, -300, 0, 435}, {}});
ev.outgoing.push_back({gluon, { 347, 306, 18, 463}, {}});
ev.outgoing.push_back({gluon, {-249, -342, 162, 453}, {}});
ev.outgoing.push_back({gluon, { 345, 312, 284, 545}, {}});
ev.outgoing.push_back({gluon, {-324, -126, 292, 454}, {}});
ev.outgoing.push_back({gluon, {-153, -180, 304, 385}, {}});
ev.incoming[0] = {gluon, { 0, 0, -1137, 1137}, {}};
ev.incoming[1] = {gluon, { 0, 0, 2103, 2103}, {}};
return ev;
case 1:
ev.outgoing.push_back({gluon, { 242, 241, -182, 387}, {}});
ev.outgoing.push_back({higgs, { 243, 238, -190, 409}, {}});
ev.outgoing.push_back({gluon, {-218, -215, -74, 315}, {}});
ev.outgoing.push_back({gluon, {-224, -224, 112, 336}, {}});
ev.outgoing.push_back({gluon, { 241, 182, 154, 339}, {}});
ev.outgoing.push_back({gluon, { -53, -234, 126, 271}, {}});
ev.outgoing.push_back({gluon, {-231, 12, 156, 279}, {}});
ev.incoming[0] = {gluon, { 0, 0, -1117, 1117}, {}};
ev.incoming[1] = {gluon, { 0, 0, 1219, 1219}, {}};
return ev;
case 2:
ev.outgoing.push_back({gluon, { 151, 102, -42, 187}, {}});
ev.outgoing.push_back({gluon, { -86, -46, -17, 99}, {}});
ev.outgoing.push_back({higgs, { 152, 153, 0, 249}, {}});
ev.outgoing.push_back({gluon, { -60, -135, 64, 161}, {}});
ev.outgoing.push_back({gluon, { 150, 123, 110, 223}, {}});
ev.outgoing.push_back({gluon, {-154, -49, 98, 189}, {}});
ev.outgoing.push_back({gluon, {-153, -148, 144, 257}, {}});
ev.incoming[0] = {gluon, { 0, 0, -504, 504}, {}};
ev.incoming[1] = {gluon, { 0, 0, 861, 861}, {}};
return ev;
case 3:
ev.outgoing.push_back({gluon, { 198, 197, -66, 287}, {}});
ev.outgoing.push_back({gluon, {-198, -189, -54, 279}, {}});
ev.outgoing.push_back({gluon, {-200, -64, 2, 210}, {}});
ev.outgoing.push_back({higgs, { 199, 158, 6, 283}, {}});
ev.outgoing.push_back({gluon, {-199, -184, 172, 321}, {}});
ev.outgoing.push_back({gluon, { 196, 168, 177, 313}, {}});
ev.outgoing.push_back({gluon, { 4, -86, 92, 126}, {}});
ev.incoming[0] = {gluon, { 0, 0, -745, 745}, {}};
ev.incoming[1] = {gluon, { 0, 0, 1074, 1074}, {}};
return ev;
case 4:
ev.outgoing.push_back({gluon, { 151, 102, -42, 187}, {}});
ev.outgoing.push_back({gluon, { -86, -133, -14, 159}, {}});
ev.outgoing.push_back({gluon, {-154, -104, -8, 186}, {}});
ev.outgoing.push_back({gluon, { -60, 11, 0, 61}, {}});
ev.outgoing.push_back({higgs, { 152, 153, 0, 249}, {}});
ev.outgoing.push_back({gluon, { 150, 125, 90, 215}, {}});
ev.outgoing.push_back({gluon, {-153, -154, 126, 251}, {}});
ev.incoming[0] = {gluon, { 0, 0, -578, 578}, {}};
ev.incoming[1] = {gluon, { 0, 0, 730, 730}, {}};
return ev;
case 5:
ev.outgoing.push_back({gluon, { -15, -90, -94, 131}, {}});
ev.outgoing.push_back({gluon, { -11, 82, -74, 111}, {}});
ev.outgoing.push_back({gluon, { 23, -80, -64, 105}, {}});
ev.outgoing.push_back({gluon, { -48, -25, -36, 65}, {}});
ev.outgoing.push_back({gluon, { -12, 99, -16, 101}, {}});
ev.outgoing.push_back({higgs, { 68, 92, -18, 170}, {}});
ev.outgoing.push_back({gluon, { -5, -78, 54, 95}, {}});
ev.incoming[0] = {gluon, { 0, 0, -513, 513}, {}};
ev.incoming[1] = {gluon, { 0, 0, 265, 265}, {}};
return ev;
case 6:
ev.outgoing.push_back({gluon, { 198, 197, -66, 287}, {}});
ev.outgoing.push_back({gluon, { 4, -84, -18, 86}, {}});
ev.outgoing.push_back({gluon, {-198, -60, -36, 210}, {}});
ev.outgoing.push_back({gluon, { 196, -78, -36, 214}, {}});
ev.outgoing.push_back({gluon, {-200, 45, 0, 205}, {}});
ev.outgoing.push_back({gluon, {-199, -178, 2, 267}, {}});
ev.outgoing.push_back({higgs, { 199, 158, 6, 283}, {}});
ev.incoming[0] = {gluon, { 0, 0, -850, 850}, {}};
ev.incoming[1] = {gluon, { 0, 0, 702, 702}, {}};
return ev;
default:
ev.outgoing.push_back({gluon, {-350, -112, -280, 462}, {}});
ev.outgoing.push_back({gluon, { 347, 266, -322, 543}, {}});
ev.outgoing.push_back({gluon, {-349, -314, -38, 471}, {}});
ev.outgoing.push_back({gluon, { 349, 348, 12, 493}, {}});
ev.outgoing.push_back({gluon, {-342, -54, 23, 347}, {}});
ev.outgoing.push_back({gluon, { 345, -134, 138, 395}, {}});
ev.incoming[0] = {gluon, { 0, 0, -1589, 1589}, {}};
ev.incoming[1] = {gluon, { 0, 0, 1122, 1122}, {}};
return ev;
}
}
if(njet == 7){
switch(pos_boson){
case -1: // jet idx: -1 0 1 2 3 4 5
ev.outgoing.push_back({gluon, { -15, -18, -54, 59}, {}});
ev.outgoing.push_back({gluon, { -11, 98, -70, 121}, {}});
ev.outgoing.push_back({gluon, { 23, -100, -64, 121}, {}});
ev.outgoing.push_back({gluon, { 68, 93, -20, 117}, {}});
ev.outgoing.push_back({gluon, { -5, -92, -12, 93}, {}});
ev.outgoing.push_back({gluon, { -48, -76, -2, 90}, {}});
ev.outgoing.push_back({gluon, { -12, 95, 56, 111}, {}});
ev.incoming[0] = {gluon, { 0, 0, -439, 439}, {}};
ev.incoming[1] = {gluon, { 0, 0, 273, 273}, {}};
return ev;
case -2: // jet idx: 0 1 2 3 4 -1 -1
ev.outgoing.push_back({gluon, { -5, -86, -82, 119}, {}});
ev.outgoing.push_back({gluon, { 68, 93, 20, 117}, {}});
ev.outgoing.push_back({gluon, { -48, -14, 20, 54}, {}});
ev.outgoing.push_back({gluon, { 23, -50, 26, 61}, {}});
ev.outgoing.push_back({gluon, { -12, 95, 56, 111}, {}});
ev.outgoing.push_back({gluon, { -15, -18, 54, 59}, {}});
ev.outgoing.push_back({gluon, { -11, -20, 88, 91}, {}});
ev.incoming[0] = {gluon, { 0, 0, -215, 215}, {}};
ev.incoming[1] = {gluon, { 0, 0, 397, 397}, {}};
return ev;
case -3: // jet idx: 0 0 1 2 2 3 4
// jet pt fraction: 0.6 0.38 1 0.49 0.51 1 1
ev.outgoing.push_back({gluon, { 23, -94, -62, 1.2e+02}, {}});
ev.outgoing.push_back({gluon, { -5, -62, -34, 71}, {}});
ev.outgoing.push_back({gluon, { 68, 93, 20, 1.2e+02}, {}});
ev.outgoing.push_back({gluon, { -12, 95, 56, 1.1e+02}, {}});
ev.outgoing.push_back({gluon, { -11, 98, 70, 1.2e+02}, {}});
ev.outgoing.push_back({gluon, { -48, -1e+02, 82, 1.4e+02}, {}});
ev.outgoing.push_back({gluon, { -15, -30, 78, 85}, {}});
ev.incoming[0] = {gluon, { 0, 0, -2.7e+02, 2.7e+02}, {}};
ev.incoming[1] = {gluon, { 0, 0, 4.8e+02, 4.8e+02}, {}};
return ev;
case -4: // jet idx: 0 1 1 2 3 4 4
// jet pt fraction: 1 0.51 0.49 1 1 0.25 0.75
ev.outgoing.push_back({gluon, { -5, -88, -64, 109}, {}});
ev.outgoing.push_back({gluon, { -11, 98, -70, 121}, {}});
ev.outgoing.push_back({gluon, { -12, 95, -56, 111}, {}});
ev.outgoing.push_back({gluon, { 68, 93, 20, 117}, {}});
ev.outgoing.push_back({gluon, { 23, -70, 22, 77}, {}});
ev.outgoing.push_back({gluon, { -15, -32, 16, 39}, {}});
ev.outgoing.push_back({gluon, { -48, -96, 75, 131}, {}});
ev.incoming[0] = {gluon, { 0, 0, -381, 381}, {}};
ev.incoming[1] = {gluon, { 0, 0, 324, 324}, {}};
return ev;
case -5: // jet idx: 0 1 -1 -1 2 3 4
ev.outgoing.push_back({gluon, { -15, -26, -62, 69}, {}});
ev.outgoing.push_back({gluon, { -48, -60, -54, 94}, {}});
ev.outgoing.push_back({gluon, { 23, 10, -14, 29}, {}});
ev.outgoing.push_back({gluon, { -5, -20, 0, 21}, {}});
ev.outgoing.push_back({gluon, { 68, 93, 20, 117}, {}});
ev.outgoing.push_back({gluon, { -11, -92, 40, 101}, {}});
ev.outgoing.push_back({gluon, { -12, 95, 56, 111}, {}});
ev.incoming[0] = {gluon, { 0, 0, -278, 278}, {}};
ev.incoming[1] = {gluon, { 0, 0, 264, 264}, {}};
return ev;
case -6: // jet idx: 0 1 1 2 -1 2 3
// jet pt fraction: 1 0.63 0.36 0.49 1 0.51 1
ev.outgoing.push_back({gluon, { 68, 93, -20, 117}, {}});
ev.outgoing.push_back({gluon, { -48, -100, 26, 114}, {}});
ev.outgoing.push_back({gluon, { -15, -62, 26, 69}, {}});
ev.outgoing.push_back({gluon, { -12, 95, 56, 111}, {}});
ev.outgoing.push_back({gluon, { -5, -28, 20, 35}, {}});
ev.outgoing.push_back({gluon, { -11, 98, 70, 121}, {}});
ev.outgoing.push_back({gluon, { 23, -96, 92, 135}, {}});
ev.incoming[0] = {gluon, { 0, 0, -216, 216}, {}};
ev.incoming[1] = {gluon, { 0, 0, 486, 486}, {}};
return ev;
case -7: // jet idx: 0 1 2 2 3 3 4
// jet pt fraction: 1 1 0.51 0.49 0.18 0.82 1
ev.outgoing.push_back({gluon, { -15, -80, -100, 129}, {}});
ev.outgoing.push_back({gluon, { 23, -96, -92, 135}, {}});
ev.outgoing.push_back({gluon, { -11, 98, -70, 121}, {}});
ev.outgoing.push_back({gluon, { -12, 95, -56, 111}, {}});
ev.outgoing.push_back({gluon, { -5, -22, -10, 25}, {}});
ev.outgoing.push_back({gluon, { -48, -88, -31, 105}, {}});
ev.outgoing.push_back({gluon, { 68, 93, 20, 117}, {}});
ev.incoming[0] = {gluon, { 0, 0, -541, 541}, {}};
ev.incoming[1] = {gluon, { 0, 0, 202, 202}, {}};
return ev;
case -8: // jet idx: 0 1 2 2 2 3 4
// jet pt fraction: 1 1 0.21 0.37 0.41 1 1
ev.outgoing.push_back({gluon, { -48, -44, -62, 90}, {}});
ev.outgoing.push_back({gluon, { -12, 95, -56, 111}, {}});
ev.outgoing.push_back({gluon, { -5, -50, -22, 55}, {}});
ev.outgoing.push_back({gluon, { 23, -90, -34, 99}, {}});
ev.outgoing.push_back({gluon, { -15, -100, -28, 105}, {}});
ev.outgoing.push_back({gluon, { 68, 93, -20, 117}, {}});
ev.outgoing.push_back({gluon, { -11, 96, 76, 123}, {}});
ev.incoming[0] = {gluon, { 0, 0, -423, 423}, {}};
ev.incoming[1] = {gluon, { 0, 0, 277, 277}, {}};
return ev;
case -9: // jet idx: 0 1 2 1 3 0 4
// jet pt fraction: 0.72 0.51 1 0.49 1 0.28 1
ev.outgoing.push_back({gluon, { -15, -98, -62, 117}, {}});
ev.outgoing.push_back({gluon, { -12, 95, -56, 111}, {}});
ev.outgoing.push_back({gluon, { 23, -76, -40, 89}, {}});
ev.outgoing.push_back({gluon, { -11, 92, -40, 101}, {}});
ev.outgoing.push_back({gluon, { -48, -68, -34, 90}, {}});
ev.outgoing.push_back({gluon, { -5, -38, -14, 41}, {}});
ev.outgoing.push_back({gluon, { 68, 93, 20, 117}, {}});
ev.incoming[0] = {gluon, { 0, 0, -446, 446}, {}};
ev.incoming[1] = {gluon, { 0, 0, 220, 220}, {}};
return ev;
case -10: // jet idx: 0 1 3 2 4 3 1
// jet pt fraction: 1 0.33 0.51 1 1 0.49 0.67
ev.outgoing.push_back({gluon, { 68, 93, 20, 117}, {}});
ev.outgoing.push_back({gluon, { -5, -48, 16, 51}, {}});
ev.outgoing.push_back({gluon, { -12, 95, 56, 111}, {}});
ev.outgoing.push_back({gluon, { 23, -76, 52, 95}, {}});
ev.outgoing.push_back({gluon, { -48, -60, 54, 94}, {}});
ev.outgoing.push_back({gluon, { -11, 92, 68, 115}, {}});
ev.outgoing.push_back({gluon, { -15, -96, 72, 121}, {}});
ev.incoming[0] = {gluon, { 0, 0, -183, 183}, {}};
ev.incoming[1] = {gluon, { 0, 0, 521, 521}, {}};
return ev;
case -11: // jet idx: 0 1 2 3 4 -1 5
// jet pt fraction: 1 1 1 1 1 1 1
ev.outgoing.push_back({gluon, { -11, 98, -70, 121}, {}});
ev.outgoing.push_back({gluon, { -15, -98, -62, 117}, {}});
ev.outgoing.push_back({gluon, { 23, -90, -2, 93}, {}});
ev.outgoing.push_back({gluon, { -48, -76, 2, 90}, {}});
ev.outgoing.push_back({gluon, { 68, 93, 20, 117}, {}});
ev.outgoing.push_back({gluon, { -5, -22, 10, 25}, {}});
ev.outgoing.push_back({gluon, { -12, 95, 56, 111}, {}});
ev.incoming[0] = {gluon, { 0, 0, -360, 360}, {}};
ev.incoming[1] = {gluon, { 0, 0, 314, 314}, {}};
return ev;
case -12: // jet idx: 0 1 -1 2 3 4 3
// jet pt fraction: 1 1 1 1 0.35 1 0.65
ev.outgoing.push_back({gluon, { 23, -94, -62, 115}, {}});
ev.outgoing.push_back({gluon, { -12, 95, -56, 111}, {}});
ev.outgoing.push_back({gluon, { -5, -28, 4, 29}, {}});
ev.outgoing.push_back({gluon, { 68, 93, 20, 117}, {}});
ev.outgoing.push_back({gluon, { -15, -58, 34, 69}, {}});
ev.outgoing.push_back({gluon, { -11, 92, 68, 115}, {}});
ev.outgoing.push_back({gluon, { -48, -100, 82, 138}, {}});
ev.incoming[0] = {gluon, { 0, 0, -302, 302}, {}};
ev.incoming[1] = {gluon, { 0, 0, 392, 392}, {}};
return ev;
case -13: // jet idx: 0 1 2 3 3 4 2
// jet pt fraction: 1 1 0.5 0.35 0.65 1 0.5
ev.outgoing.push_back({gluon, { -15, -98, -62, 117}, {}});
ev.outgoing.push_back({gluon, { 68, 93, 20, 117}, {}});
ev.outgoing.push_back({gluon, { -12, 95, 56, 111}, {}});
ev.outgoing.push_back({gluon, { -5, -28, 20, 35}, {}});
ev.outgoing.push_back({gluon, { -48, -96, 75, 131}, {}});
ev.outgoing.push_back({gluon, { 23, -62, 50, 83}, {}});
ev.outgoing.push_back({gluon, { -11, 96, 76, 123}, {}});
ev.incoming[0] = {gluon, { 0, 0, -241, 241}, {}};
ev.incoming[1] = {gluon, { 0, 0, 476, 476}, {}};
return ev;
case -14: // jet idx: 0 1 2 3 3 4 2
// jet pt fraction: 1 1 0.52 0.35 0.65 1 0.48
ev.outgoing.push_back({gluon, { 23, -94, -62, 115}, {}});
ev.outgoing.push_back({gluon, { 68, 93, 20, 117}, {}});
ev.outgoing.push_back({gluon, { -12, 95, 56, 111}, {}});
ev.outgoing.push_back({gluon, { -15, -96, 72, 121}, {}});
ev.outgoing.push_back({gluon, { -5, -42, 38, 57}, {}});
ev.outgoing.push_back({gluon, { -48, -44, 62, 90}, {}});
ev.outgoing.push_back({gluon, { -11, 88, 88, 125}, {}});
ev.incoming[0] = {gluon, { 0, 0, -231, 231}, {}};
ev.incoming[1] = {gluon, { 0, 0, 505, 505}, {}};
return ev;
case -15: // jet idx: 0 -1 1 0 2 3 4
// jet pt fraction: 0.51 1 1 0.49 1 1 1
ev.outgoing.push_back({gluon, { -11, 98, -70, 121}, {}});
ev.outgoing.push_back({gluon, { -5, -16, -12, 21}, {}});
ev.outgoing.push_back({gluon, { 23, -94, -62, 115}, {}});
ev.outgoing.push_back({gluon, { -12, 95, -56, 111}, {}});
ev.outgoing.push_back({gluon, { 68, 93, 20, 117}, {}});
ev.outgoing.push_back({gluon, { -48, -76, 70, 114}, {}});
ev.outgoing.push_back({gluon, { -15, -100, 80, 129}, {}});
ev.incoming[0] = {gluon, { 0, 0, -379, 379}, {}};
ev.incoming[1] = {gluon, { 0, 0, 349, 349}, {}};
return ev;
}
}
throw HEJ::unknown_option{"unknown process"};
}
HEJ::Event::EventData parse_configuration(
std::array<std::string,2> const & in, std::vector<std::string> const & out,
int const overwrite_boson
){
auto boson = std::find_if(out.cbegin(), out.cend(),
[](std::string id){ return !HEJ::is_parton(HEJ::to_ParticleID(id)); });
int const pos_boson = (overwrite_boson!=0)?overwrite_boson:
((boson == out.cend())?-1:std::distance(out.cbegin(), boson));
size_t njets = out.size();
if( (overwrite_boson == 0) && boson != out.cend()) --njets;
HEJ::Event::EventData ev{get_process(njets, pos_boson)};
ASSERT((pos_boson<0) || (ev.outgoing[pos_boson].type == HEJ::ParticleID::higgs));
for(size_t i=0; i<out.size(); ++i){
ev.outgoing[i].type = HEJ::to_ParticleID(out[i]);
// decay W
if( std::abs(ev.outgoing[i].type) == HEJ::ParticleID::Wp )
ev.decays[i]=decay_W(ev.outgoing[i]);
}
for(size_t i=0; i<in.size(); ++i){
ev.incoming[i].type = HEJ::to_ParticleID(in[i]);
}
shuffle_particles(ev);
return ev;
}
namespace {
static std::mt19937_64 ran{0};
}
void shuffle_particles(HEJ::Event::EventData & ev) {
// incoming
std::shuffle(begin(ev.incoming), end(ev.incoming), ran);
// outgoing (through index)
auto old_outgoing = std::move(ev).outgoing;
std::vector<size_t> idx(old_outgoing.size());
std::iota(idx.begin(), idx.end(), 0);
std::shuffle(begin(idx), end(idx), ran);
ev.outgoing.clear();
ev.outgoing.reserve(old_outgoing.size());
for(size_t i: idx) {
ev.outgoing.emplace_back(std::move(old_outgoing[i]));
}
// find decays again
if(!ev.decays.empty()){
auto old_decays = std::move(ev).decays;
ev.decays.clear();
for(size_t i=0; i<idx.size(); ++i) {
auto decay = old_decays.find(idx[i]);
if(decay != old_decays.end())
ev.decays.emplace(i, std::move(decay->second));
}
for(auto & decay: ev.decays){
std::shuffle(begin(decay.second), end(decay.second), ran);
}
}
}
std::vector<HEJ::Particle> decay_W( HEJ::Particle const & parent ){
if(parent.m() == 0.) // we can't decay massless partons
return {};
std::array<HEJ::ParticleID, 2> decays;
if(parent.type==HEJ::ParticleID::Wp){
// order matters: first particle, second anti
decays[0] = HEJ::ParticleID::nu_e;
decays[1] = HEJ::ParticleID::e_bar;
} else {
// this function is for testing: we don't check that parent==W boson
decays[0] = HEJ::ParticleID::e;
decays[1] = HEJ::ParticleID::nu_e_bar;
}
std::vector<HEJ::Particle> decay_products(decays.size());
for(size_t i = 0; i < decays.size(); ++i){
decay_products[i].type = decays[i];
}
// choose polar and azimuth angle in parent rest frame
const double E = parent.m()/2;
const double theta = 2.*M_PI*ran()/(1.*ran.max());
const double cos_phi = 2.*ran()/(1.*ran.max())-1.;
const double sin_phi = sqrt(1. - cos_phi*cos_phi); // Know 0 < phi < pi
const double px = E*cos(theta)*sin_phi;
const double py = E*sin(theta)*sin_phi;
const double pz = E*cos_phi;
decay_products[0].p.reset(px, py, pz, E);
decay_products[1].p.reset(-px, -py, -pz, E);
for(auto & particle: decay_products) particle.p.boost(parent.p);
return decay_products;
}

File Metadata

Mime Type
text/x-diff
Expires
Tue, Nov 19, 2:46 PM (1 d, 10 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
3804806
Default Alt Text
(60 KB)

Event Timeline