Page Menu
Home
HEPForge
Search
Configure Global Search
Log In
Files
F7877953
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
112 KB
Subscribers
None
View Options
diff --git a/src/Event.cc b/src/Event.cc
index e9ee7cf..661a565 100644
--- a/src/Event.cc
+++ b/src/Event.cc
@@ -1,889 +1,912 @@
/**
* \authors The HEJ collaboration (see AUTHORS for details)
* \date 2019
* \copyright GPLv2 or later
*/
#include "HEJ/Event.hh"
#include <algorithm>
#include <assert.h>
#include <numeric>
#include <unordered_set>
#include <utility>
#include "LHEF/LHEF.h"
#include "fastjet/JetDefinition.hh"
#include "HEJ/Constants.hh"
#include "HEJ/exceptions.hh"
#include "HEJ/PDG_codes.hh"
namespace HEJ{
namespace {
constexpr int status_in = -1;
constexpr int status_decayed = 2;
constexpr int status_out = 1;
/// @name helper functions to determine event type
//@{
/**
* \brief check if final state valid for HEJ
*
* check if there is at most one photon, W, H, Z in the final state
* and all the rest are quarks or gluons
*/
bool final_state_ok(std::vector<Particle> const & outgoing){
bool has_AWZH_boson = false;
for(auto const & out: outgoing){
if(is_AWZH_boson(out.type)){
if(has_AWZH_boson) return false;
has_AWZH_boson = true;
}
else if(! is_parton(out.type)) return false;
}
return true;
}
/**
+ * returns all EventTypes implemented in HEJ
+ */
+ size_t implemented_types(std::vector<Particle> const & bosons){
+ using namespace event_type;
+ if(bosons.empty()) return FKL | unob | unof; // pure jets
+ if(bosons.size()>1) return non_resummable; // multi boson
+ switch (bosons[0].type) {
+ case ParticleID::Wp:
+ case ParticleID::Wm:
+ return FKL | unob | unof | qqxexb | qqxexf | qqxmid;
+ case ParticleID::h:
+ return FKL | unob | unof;
+ default:
+ return non_resummable;
+ }
+ }
+
+ /**
* \brief function which determines if type change is consistent with Wp emission.
* @param in incoming Particle id
* @param out outgoing Particle id
* @param qqx Current both incoming/both outgoing?
*
* \see is_Wm_Change
*/
bool is_Wp_Change(ParticleID in, ParticleID out, bool qqx){
if(!qqx && (in==-1 || in== 2 || in==-3 || in== 4)) return out== (in-1);
if( qqx && (in== 1 || in==-2 || in== 3 || in==-4)) return out==-(in+1);
return false;
}
/**
* \brief function which determines if type change is consistent with Wm emission.
* @param in incoming Particle id
* @param out outgoing Particle id
* @param qqx Current both incoming/both outgoing?
*
* Ensures that change type of quark line is possible by a flavour changing
* Wm emission. Allows checking of qqx currents also.
*/
bool is_Wm_Change(ParticleID in, ParticleID out, bool qqx){
if(!qqx && (in== 1 || in==-2 || in== 3 || in==-4)) return out== (in+1);
if( qqx && (in==-1 || in== 2 || in==-3 || in== 4)) return out==-(in-1);
return false;
}
/**
* \brief checks if particle type remains same from incoming to outgoing
* @param in incoming Particle
* @param out outgoing Particle
* @param qqx Current both incoming/outgoing?
*/
bool no_flavour_change(ParticleID in, ParticleID out, bool qqx){
const int qqxCurrent = qqx?-1:1;
if(abs(in)<=6 || in==pid::gluon) return (in==out*qqxCurrent);
else return false;
}
bool has_2_jets(Event const & event){
return event.jets().size() >= 2;
}
/**
* \brief check if we have a valid Impact factor
* @param in incoming Particle
* @param out outgoing Particle
* @param qqx Current both incoming/outgoing?
* @param qqx returns +1 if Wp, -1 if Wm, else 0
*/
bool is_valid_impact_factor(
ParticleID in, ParticleID out, bool qqx, int & W_change
){
if( no_flavour_change(in, out, qqx) ){
return true;
}
if( is_Wp_Change(in, out, qqx) ) {
W_change+=1;
return true;
}
if( is_Wm_Change(in, out, qqx) ) {
W_change-=1;
return true;
}
return false;
}
//! Returns all possible classifications from the impact factors
// the beginning points are changed s.t. after the the classification they
// point to the beginning of the (potential) FKL chain
// sets W_change: + if Wp change
// 0 if no change
// - if Wm change
// This function can be used with forward & backwards iterators
template<class OutIterator>
size_t possible_impact_factors(
ParticleID incoming_id, // incoming
OutIterator & begin_out, OutIterator const & end_out, // outgoing
int & W_change, std::vector<Particle> const & boson,
bool const backward // backward?
){
using namespace event_type;
assert(boson.size() < 2);
// keep track of all states that we don't test
size_t not_tested = qqxmid;
if(backward)
not_tested |= unof | qqxexf;
else
not_tested |= unob | qqxexb;
// Is this LL current?
if( is_valid_impact_factor(incoming_id, begin_out->type, false, W_change) ){
++begin_out;
return not_tested | FKL;
}
// or NLL current?
// -> needs two partons in two different jets
if( std::distance(begin_out, end_out)>=2
){
// Is this unordered emisson?
if( incoming_id!=pid::gluon && begin_out->type==pid::gluon ){
if( is_valid_impact_factor(
incoming_id, (begin_out+1)->type, false, W_change )
){
// veto Higgs inside uno
assert((begin_out+1)<end_out);
if( !boson.empty() && boson.front().type == ParticleID::h
){
if( (backward && boson.front().rapidity() < (begin_out+1)->rapidity())
||(!backward && boson.front().rapidity() > (begin_out+1)->rapidity()))
return non_resummable;
}
begin_out+=2;
return not_tested | (backward?unob:unof);
}
}
// Is this QQbar?
else if( incoming_id==pid::gluon ){
if( is_valid_impact_factor(
begin_out->type, (begin_out+1)->type, true, W_change )
){
// veto Higgs inside qqx
assert((begin_out+1)<end_out);
if( !boson.empty() && boson.front().type == ParticleID::h
){
if( (backward && boson.front().rapidity() < (begin_out+1)->rapidity())
||(!backward && boson.front().rapidity() > (begin_out+1)->rapidity()))
return non_resummable;
}
begin_out+=2;
return not_tested | (backward?qqxexb:qqxexf);
}
}
}
return non_resummable;
}
//! Returns all possible classifications from central emissions
// the beginning points are changed s.t. after the the classification they
// point to the end of the emission chain
// sets W_change: + if Wp change
// 0 if no change
// - if Wm change
template<class OutIterator>
size_t possible_central(
OutIterator & begin_out, OutIterator const & end_out,
int & W_change, std::vector<Particle> const & boson,
OutIterator & qqx_pos
){
using namespace event_type;
assert(boson.size() < 2);
// if we already passed the central chain,
// then it is not a valid all-order state
if(std::distance(begin_out, end_out) < 0) return non_resummable;
// keep track of all states that we don't test
size_t possible = unob | unof
| qqxexb | qqxexf;
// Find the first non-gluon/non-FKL
while( (begin_out->type==pid::gluon) && (begin_out<end_out) ){
++begin_out;
}
// end of chain -> FKL
if( begin_out==end_out ){
return possible | FKL;
}
// is this a qqbar-pair?
// needs two partons in two separate jets
if( is_valid_impact_factor(
begin_out->type, (begin_out+1)->type, true, W_change )
){
// veto Higgs inside qqx
if( !boson.empty() && boson.front().type == ParticleID::h
&& boson.front().rapidity() > begin_out->rapidity()
&& boson.front().rapidity() < (begin_out+1)->rapidity()
){
return non_resummable;
}
qqx_pos=begin_out;
begin_out+=2;
// remaining chain should be pure gluon/FKL
for(; begin_out<end_out; ++begin_out){
if(begin_out->type != pid::gluon) return non_resummable;
}
return possible | qqxmid;
}
return non_resummable;
}
bool invalid_jet(std::unordered_set<int> & other, int const idx){
if(idx<0) return true;
if(other.find(idx) != other.cend()) return true;
other.insert(idx);
return false;
}
bool jets_ok( size_t const final_type,
std::vector<int> const & jet_idx, size_t const qqx_pos
){
using namespace event_type;
std::unordered_set<int> other;
auto idx_begin{jet_idx.cbegin()};
auto idx_end{jet_idx.crbegin()};
// always seperate extremal jets
if(invalid_jet(other, *idx_begin)) return false;
if(invalid_jet(other, *idx_end)) return false;
// unob -> second parton in own jet
if( (final_type & (unob | qqxexb))
&& invalid_jet(other, *(idx_begin+1)) ) return false;
if( (final_type & (unof | qqxexf))
&& invalid_jet(other, *(idx_end+1)) ) return false;
assert( !(final_type & qqxmid) || jet_idx.size()>qqx_pos+1 );
if( (final_type & qqxmid)
&& ( invalid_jet(other, *(idx_begin+qqx_pos))
|| invalid_jet(other, *(idx_begin+qqx_pos+1)) ) ) return false;
return true;
}
/**
* \brief Checks for all event types
* @param ev Event
* @returns Event Type
*
*/
event_type::EventType classify(Event const & ev){
using namespace event_type;
if(! has_2_jets(ev))
return no_2_jets;
// currently we can't handle multiple boson states in the ME. So they are
// considered "bad_final_state" even though the "classify" could work with
// them.
if(! final_state_ok(ev.outgoing()))
return bad_final_state;
// initialise variables
auto const & in = ev.incoming();
auto const & out = filter_partons(ev.outgoing());
assert(std::distance(begin(in), end(in)) == 2);
assert(out.size() >= 2);
assert(std::distance(begin(out), end(out)) >= 2);
assert(std::is_sorted(begin(out), end(out), rapidity_less{}));
auto const boson{ filter_AWZH_bosons(ev.outgoing()) };
// we only allow one boson through final_state_ok
assert(boson.size()<=1);
// keep track of potential W couplings, at the end the sum should be 0
int remaining_Wp = 0;
int remaining_Wm = 0;
if(!boson.empty() && abs(boson.front().type) == ParticleID::Wp ){
if(boson.front().type>0) ++remaining_Wp;
else ++remaining_Wm;
}
int W_change = 0;
// range for current checks
auto begin_out{out.cbegin()};
auto end_out{out.crbegin()};
size_t final_type = ~(no_2_jets | bad_final_state);
// check forward impact factor
final_type &= possible_impact_factors(
in.front().type,
begin_out, end_out.base(),
W_change, boson, true );
if( final_type == non_resummable )
return non_resummable;
if(W_change>0) remaining_Wp-=W_change;
else if(W_change<0) remaining_Wm+=W_change;
W_change = 0;
// check backward impact factor
final_type &= possible_impact_factors(
in.back().type,
end_out, std::make_reverse_iterator(begin_out),
W_change, boson, false );
if( final_type == non_resummable )
return non_resummable;
if(W_change>0) remaining_Wp-=W_change;
else if(W_change<0) remaining_Wm+=W_change;
W_change = 0;
// check central emissions
auto qqx_pos{out.cend()};
final_type &= possible_central(
begin_out, end_out.base(), W_change, boson, qqx_pos );
if( final_type == non_resummable )
return non_resummable;
assert( !(final_type&qqxmid) || qqx_pos != out.cend() );
if(W_change>0) remaining_Wp-=W_change;
else if(W_change<0) remaining_Wm+=W_change;
// Check whether the right number of Ws are present
if( remaining_Wp != 0 || remaining_Wm != 0 ) return non_resummable;
// result has to be unique
if( (final_type & (final_type-1)) != 0) return non_resummable;
// check jet configurations
if(!jets_ok( final_type,
ev.particle_jet_indices( ev.jets() ),
std::distance( out.cbegin(), qqx_pos) ))
return non_resummable;
+ // check that each sub processes is implemented
+ // (has to be done at the end)
+ if( (final_type & ~implemented_types(boson)) != 0 )
+ return non_resummable;
+
return static_cast<EventType>(final_type);
}
//@}
Particle extract_particle(LHEF::HEPEUP const & hepeup, int i){
const ParticleID id = static_cast<ParticleID>(hepeup.IDUP[i]);
const fastjet::PseudoJet momentum{
hepeup.PUP[i][0], hepeup.PUP[i][1],
hepeup.PUP[i][2], hepeup.PUP[i][3]
};
if(is_parton(id))
return Particle{ id, std::move(momentum), hepeup.ICOLUP[i] };
return Particle{ id, std::move(momentum), {} };
}
bool is_decay_product(std::pair<int, int> const & mothers){
if(mothers.first == 0) return false;
return mothers.second == 0 || mothers.first == mothers.second;
}
} // namespace anonymous
Event::EventData::EventData(LHEF::HEPEUP const & hepeup){
parameters.central = EventParameters{
hepeup.scales.mur, hepeup.scales.muf, hepeup.weight()
};
size_t in_idx = 0;
for (int i = 0; i < hepeup.NUP; ++i) {
// skip decay products
// we will add them later on, but we have to ensure that
// the decayed particle is added before
if(is_decay_product(hepeup.MOTHUP[i])) continue;
auto particle = extract_particle(hepeup, i);
// needed to identify mother particles for decay products
particle.p.set_user_index(i+1);
if(hepeup.ISTUP[i] == status_in){
if(in_idx > incoming.size()) {
throw std::invalid_argument{
"Event has too many incoming particles"
};
}
incoming[in_idx++] = std::move(particle);
}
else outgoing.emplace_back(std::move(particle));
}
// add decay products
for (int i = 0; i < hepeup.NUP; ++i) {
if(!is_decay_product(hepeup.MOTHUP[i])) continue;
const int mother_id = hepeup.MOTHUP[i].first;
const auto mother = std::find_if(
begin(outgoing), end(outgoing),
[mother_id](Particle const & particle){
return particle.p.user_index() == mother_id;
}
);
if(mother == end(outgoing)){
throw std::invalid_argument{"invalid decay product parent"};
}
const int mother_idx = std::distance(begin(outgoing), mother);
assert(mother_idx >= 0);
decays[mother_idx].emplace_back(extract_particle(hepeup, i));
}
}
Event::Event(
UnclusteredEvent const & ev,
fastjet::JetDefinition const & jet_def, double const min_jet_pt
):
Event( Event::EventData{
ev.incoming, ev.outgoing, ev.decays,
Parameters<EventParameters>{ev.central, ev.variations}
}.cluster(jet_def, min_jet_pt) )
{}
//! @TODO remove in HEJ 2.2.0
UnclusteredEvent::UnclusteredEvent(LHEF::HEPEUP const & hepeup){
Event::EventData const evData{hepeup};
incoming = evData.incoming;
outgoing = evData.outgoing;
decays = evData.decays;
central = evData.parameters.central;
variations = evData.parameters.variations;
}
void Event::EventData::sort(){
// sort particles
std::sort(
begin(incoming), end(incoming),
[](Particle o1, Particle o2){return o1.p.pz()<o2.p.pz();}
);
auto old_outgoing = std::move(outgoing);
std::vector<size_t> idx(old_outgoing.size());
std::iota(idx.begin(), idx.end(), 0);
std::sort(idx.begin(), idx.end(), [&old_outgoing](size_t i, size_t j){
return old_outgoing[i].rapidity() < old_outgoing[j].rapidity();
});
outgoing.clear();
outgoing.reserve(old_outgoing.size());
for(size_t i: idx) {
outgoing.emplace_back(std::move(old_outgoing[i]));
}
// find decays again
if(!decays.empty()){
auto old_decays = std::move(decays);
decays.clear();
for(size_t i=0; i<idx.size(); ++i) {
auto decay = old_decays.find(idx[i]);
if(decay != old_decays.end())
decays.emplace(i, std::move(decay->second));
}
assert(old_decays.size() == decays.size());
}
}
namespace {
Particle reconstruct_boson(std::vector<Particle> const & leptons) {
Particle decayed_boson;
decayed_boson.p = leptons[0].p + leptons[1].p;
const int pidsum = leptons[0].type + leptons[1].type;
if(pidsum == +1) {
assert(is_antilepton(leptons[0]));
if(is_antineutrino(leptons[0])) {
throw not_implemented{"lepton-flavour violating final state"};
}
assert(is_neutrino(leptons[1]));
// charged antilepton + neutrino means we had a W+
decayed_boson.type = pid::Wp;
}
else if(pidsum == -1) {
assert(is_antilepton(leptons[0]));
if(is_neutrino(leptons[1])) {
throw not_implemented{"lepton-flavour violating final state"};
}
assert(is_antineutrino(leptons[0]));
// charged lepton + antineutrino means we had a W-
decayed_boson.type = pid::Wm;
}
else {
throw not_implemented{
"final state with leptons "
+ name(leptons[0].type)
+ " and "
+ name(leptons[1].type)
};
}
return decayed_boson;
}
}
void Event::EventData::reconstruct_intermediate() {
const auto begin_leptons = std::partition(
begin(outgoing), end(outgoing),
[](Particle const & p) {return !is_anylepton(p);}
);
if(begin_leptons == end(outgoing)) return;
assert(is_anylepton(*begin_leptons));
std::vector<Particle> leptons(begin_leptons, end(outgoing));
outgoing.erase(begin_leptons, end(outgoing));
if(leptons.size() != 2) {
throw not_implemented{"Final states with one or more than two leptons"};
}
std::sort(
begin(leptons), end(leptons),
[](Particle const & p0, Particle const & p1) {
return p0.type < p1.type;
}
);
outgoing.emplace_back(reconstruct_boson(leptons));
decays.emplace(outgoing.size()-1, std::move(leptons));
}
Event Event::EventData::cluster(
fastjet::JetDefinition const & jet_def, double const min_jet_pt
){
sort();
Event ev{ std::move(incoming), std::move(outgoing), std::move(decays),
std::move(parameters),
jet_def, min_jet_pt
};
assert(std::is_sorted(begin(ev.outgoing_), end(ev.outgoing_),
rapidity_less{}));
ev.type_ = classify(ev);
return ev;
}
Event::Event(
std::array<Particle, 2> && incoming,
std::vector<Particle> && outgoing,
std::unordered_map<size_t, std::vector<Particle>> && decays,
Parameters<EventParameters> && parameters,
fastjet::JetDefinition const & jet_def,
double const min_jet_pt
): incoming_{std::move(incoming)},
outgoing_{std::move(outgoing)},
decays_{std::move(decays)},
parameters_{std::move(parameters)},
cs_{ to_PseudoJet( filter_partons(outgoing_) ), jet_def },
min_jet_pt_{min_jet_pt}
{
jets_ = sorted_by_rapidity(cs_.inclusive_jets(min_jet_pt_));
}
namespace {
// check that Particles have a reasonable colour
bool correct_colour(Particle const & part){
ParticleID id{ part.type };
if(!is_parton(id))
return !part.colour;
if(!part.colour)
return false;
Colour const & col{ *part.colour };
if(is_quark(id))
return col.first != 0 && col.second == 0;
if(is_antiquark(id))
return col.first == 0 && col.second != 0;
assert(id==ParticleID::gluon);
return col.first != 0 && col.second != 0 && col.first != col.second;
}
}
bool Event::is_leading_colour() const {
if( !correct_colour(incoming()[0]) || !correct_colour(incoming()[1]) )
return false;
Colour line_colour = *incoming()[0].colour;
std::swap(line_colour.first, line_colour.second);
for(auto const & part: outgoing()){
// reasonable colour
if(!correct_colour(part))
return false;
if(!is_parton(part)) // skip colour neutral particles
continue;
// if possible connect to line
if( line_colour.first == part.colour->second )
line_colour.first = part.colour->first;
else if( line_colour.second == part.colour->first )
line_colour.second = part.colour->second;
else
return false;
// no colour singlet exchange/disconnected diagram
if(line_colour.first == line_colour.second)
return false;
}
return (incoming()[1].colour->first == line_colour.first)
&& (incoming()[1].colour->second == line_colour.second);
}
namespace {
void connect_incoming(Particle & in, int & colour, int & anti_colour){
in.colour = std::make_pair(anti_colour, colour);
// gluon
if(in.type == pid::gluon)
return;
if(in.type > 0){
// quark
assert(is_quark(in));
in.colour->second = 0;
colour*=-1;
return;
}
// anti-quark
assert(is_antiquark(in));
in.colour->first = 0;
anti_colour*=-1;
return;
}
}
bool Event::generate_colours(RNG & ran){
// generate only for HEJ events
if(!event_type::is_resummable(type()))
return false;
assert(std::is_sorted(
begin(outgoing()), end(outgoing()), rapidity_less{}));
assert(incoming()[0].pz() < incoming()[1].pz());
// positive (anti-)colour -> can connect
// negative (anti-)colour -> not available/used up by (anti-)quark
int colour = COLOUR_OFFSET;
int anti_colour = colour+1;
// initialise first
connect_incoming(incoming_[0], colour, anti_colour);
for(auto & part: outgoing_){
assert(colour>0 || anti_colour>0);
if(part.type == ParticleID::gluon){
// gluon
if(colour>0 && anti_colour>0){
// on g line => connect to colour OR anti-colour (random)
if(ran.flat() < 0.5){
part.colour = std::make_pair(colour+2,colour);
colour+=2;
} else {
part.colour = std::make_pair(anti_colour, anti_colour+2);
anti_colour+=2;
}
} else if(colour > 0){
// on q line => connect to available colour
part.colour = std::make_pair(colour+2, colour);
colour+=2;
} else {
assert(colour<0 && anti_colour>0);
// on qx line => connect to available anti-colour
part.colour = std::make_pair(anti_colour, anti_colour+2);
anti_colour+=2;
}
} else if(is_quark(part)) {
// quark
assert(anti_colour>0);
if(colour>0){
// on g line => connect and remove anti-colour
part.colour = std::make_pair(anti_colour, 0);
anti_colour+=2;
anti_colour*=-1;
} else {
// on qx line => new colour
colour*=-1;
part.colour = std::make_pair(colour, 0);
}
} else if(is_antiquark(part)) {
// anti-quark
assert(colour>0);
if(anti_colour>0){
// on g line => connect and remove colour
part.colour = std::make_pair(0, colour);
colour+=2;
colour*=-1;
} else {
// on q line => new anti-colour
anti_colour*=-1;
part.colour = std::make_pair(0, anti_colour);
}
} else { // not a parton
assert(!is_parton(part));
part.colour = {};
}
}
// Connect last
connect_incoming(incoming_[1], anti_colour, colour);
assert(is_leading_colour());
return true;
} // generate_colours
Event::ConstPartonIterator Event::begin_partons() const {
return cbegin_partons();
};
Event::ConstPartonIterator Event::cbegin_partons() const {
return boost::make_filter_iterator(
static_cast<bool (*)(Particle const &)>(is_parton),
cbegin(outgoing()),
cend(outgoing())
);
};
Event::ConstPartonIterator Event::end_partons() const {
return cend_partons();
};
Event::ConstPartonIterator Event::cend_partons() const {
return boost::make_filter_iterator(
static_cast<bool (*)(Particle const &)>(is_parton),
cend(outgoing()),
cend(outgoing())
);
};
namespace {
void print_momentum(std::ostream & os, fastjet::PseudoJet const & part){
const std::streamsize orig_prec = os.precision();
os <<std::scientific<<std::setprecision(6) << "["
<<std::setw(13)<<std::right<< part.px() << ", "
<<std::setw(13)<<std::right<< part.py() << ", "
<<std::setw(13)<<std::right<< part.pz() << ", "
<<std::setw(13)<<std::right<< part.E() << "]"<< std::fixed;
os.precision(orig_prec);
}
void print_colour(std::ostream & os, optional<Colour> const & col){
if(!col)
os << "(no color)"; // American spelling for better alignment
else
os << "(" <<std::setw(3)<<std::right<< col->first
<< ", " <<std::setw(3)<<std::right<< col->second << ")";
}
}
std::ostream& operator<<(std::ostream & os, Event const & ev){
const std::streamsize orig_prec = os.precision();
os <<std::setprecision(4)<<std::fixed;
os << "########## " << event_type::name(ev.type()) << " ##########" << std::endl;
os << "Incoming particles:\n";
for(auto const & in: ev.incoming()){
os <<std::setw(3)<< in.type << ": ";
print_colour(os, in.colour);
os << " ";
print_momentum(os, in.p);
os << std::endl;
}
os << "\nOutgoing particles: " << ev.outgoing().size() << "\n";
for(auto const & out: ev.outgoing()){
os <<std::setw(3)<< out.type << ": ";
print_colour(os, out.colour);
os << " ";
print_momentum(os, out.p);
os << " => rapidity="
<<std::setw(7)<<std::right<< out.rapidity() << std::endl;
}
os << "\nForming Jets: " << ev.jets().size() << "\n";
for(auto const & jet: ev.jets()){
print_momentum(os, jet);
os << " => rapidity="
<<std::setw(7)<<std::right<< jet.rapidity() << std::endl;
}
if(ev.decays().size() > 0 ){
os << "\nDecays: " << ev.decays().size() << "\n";
for(auto const & decay: ev.decays()){
os <<std::setw(3)<< ev.outgoing()[decay.first].type
<< " (" << decay.first << ") to:\n";
for(auto const & out: decay.second){
os <<" "<<std::setw(3)<< out.type << ": ";
print_momentum(os, out.p);
os << " => rapidity="
<<std::setw(7)<<std::right<< out.rapidity() << std::endl;
}
}
}
os << std::defaultfloat;
os.precision(orig_prec);
return os;
}
double shat(Event const & ev){
return (ev.incoming()[0].p + ev.incoming()[1].p).m2();
}
LHEF::HEPEUP to_HEPEUP(Event const & event, LHEF::HEPRUP * heprup){
LHEF::HEPEUP result;
result.heprup = heprup;
result.weights = {{event.central().weight, nullptr}};
for(auto const & var: event.variations()){
result.weights.emplace_back(var.weight, nullptr);
}
size_t num_particles = event.incoming().size() + event.outgoing().size();
for(auto const & decay: event.decays()) num_particles += decay.second.size();
result.NUP = num_particles;
// the following entries are pretty much meaningless
result.IDPRUP = event.type(); // event type
result.AQEDUP = 1./128.; // alpha_EW
//result.AQCDUP = 0.118 // alpha_QCD
// end meaningless part
result.XWGTUP = event.central().weight;
result.SCALUP = event.central().muf;
result.scales.muf = event.central().muf;
result.scales.mur = event.central().mur;
result.scales.SCALUP = event.central().muf;
result.pdfinfo.p1 = event.incoming().front().type;
result.pdfinfo.p2 = event.incoming().back().type;
result.pdfinfo.scale = event.central().muf;
result.IDUP.reserve(num_particles); // PID
result.ISTUP.reserve(num_particles); // status (in, out, decay)
result.PUP.reserve(num_particles); // momentum
result.MOTHUP.reserve(num_particles); // index mother particle
result.ICOLUP.reserve(num_particles); // colour
// incoming
std::array<Particle, 2> incoming{ event.incoming() };
// First incoming should be positive pz according to LHE standard
// (or at least most (everyone?) do it this way, and Pythia assumes it)
if(incoming[0].pz() < incoming[1].pz())
std::swap(incoming[0], incoming[1]);
for(Particle const & in: incoming){
result.IDUP.emplace_back(in.type);
result.ISTUP.emplace_back(status_in);
result.PUP.push_back({in.p[0], in.p[1], in.p[2], in.p[3], in.p.m()});
result.MOTHUP.emplace_back(0, 0);
assert(in.colour);
result.ICOLUP.emplace_back(*in.colour);
}
// outgoing
for(size_t i = 0; i < event.outgoing().size(); ++i){
Particle const & out = event.outgoing()[i];
result.IDUP.emplace_back(out.type);
const int status = event.decays().count(i)?status_decayed:status_out;
result.ISTUP.emplace_back(status);
result.PUP.push_back({out.p[0], out.p[1], out.p[2], out.p[3], out.p.m()});
result.MOTHUP.emplace_back(1, 2);
if(out.colour)
result.ICOLUP.emplace_back(*out.colour);
else{
assert(is_AWZH_boson(out));
result.ICOLUP.emplace_back(std::make_pair(0,0));
}
}
// decays
for(auto const & decay: event.decays()){
for(auto const out: decay.second){
result.IDUP.emplace_back(out.type);
result.ISTUP.emplace_back(status_out);
result.PUP.push_back({out.p[0], out.p[1], out.p[2], out.p[3], out.p.m()});
const size_t mother_idx = 1 + event.incoming().size() + decay.first;
result.MOTHUP.emplace_back(mother_idx, mother_idx);
result.ICOLUP.emplace_back(0,0);
}
}
assert(result.ICOLUP.size() == num_particles);
static constexpr double unknown_spin = 9.; //per Les Houches accord
result.VTIMUP = std::vector<double>(num_particles, unknown_spin);
result.SPINUP = result.VTIMUP;
return result;
}
}
diff --git a/t/classify_ref_4j b/t/classify_ref_4j
index 701338a..056dd0f 100644
--- a/t/classify_ref_4j
+++ b/t/classify_ref_4j
@@ -1,3255 +1,3255 @@
4
4
0
0
4
0
4
4
4
16
4
0
0
0
4
0
0
4
0
4
0
0
4
0
0
4
0
4
0
4
0
0
0
-64
+0
4
4
2
0
0
2
4
0
0
4
4
4
4
0
4
0
0
4
0
2
4
4
0
0
0
4
0
4
0
4
4
-64
+0
4
4
0
4
4
4
0
4
4
0
0
-32
+0
0
4
4
-64
+0
2
0
0
4
0
0
0
0
4
0
0
4
4
0
0
0
4
0
0
0
0
0
0
0
4
2
4
0
0
4
0
0
4
0
4
4
0
0
0
4
0
4
4
4
4
-64
+0
0
4
4
0
4
4
4
2
0
0
4
4
0
0
0
4
0
4
4
0
0
4
4
2
4
2
4
4
0
0
0
4
4
0
4
0
8
4
-128
+0
4
0
4
4
2
0
-64
+0
2
2
8
4
4
-128
+0
4
0
8
4
4
16
8
0
4
0
0
0
0
4
0
0
4
4
0
0
4
4
0
2
0
0
4
4
0
4
4
0
0
4
4
4
0
2
0
4
4
4
4
0
4
0
0
0
0
4
0
4
4
-64
+0
0
0
4
0
0
4
0
4
0
0
0
4
4
0
4
4
4
0
4
0
0
4
0
0
-64
+0
0
8
4
4
4
4
0
4
8
4
8
4
4
4
4
0
4
4
4
0
0
4
0
0
4
0
4
0
4
16
0
0
0
2
0
0
4
0
0
4
0
-64
+0
8
4
0
0
0
0
-32
+0
4
4
4
16
0
0
4
16
4
4
0
0
4
0
0
2
0
0
-64
+0
0
0
0
0
0
4
0
4
0
0
4
2
4
4
0
0
4
4
4
0
0
4
0
0
4
0
0
4
0
4
0
0
4
4
4
4
0
0
-64
+0
4
4
4
2
0
2
0
0
0
4
0
4
4
0
4
0
4
4
0
4
0
2
0
0
4
0
0
0
-64
+0
4
0
4
0
0
0
4
0
4
4
0
4
0
4
4
16
0
4
4
0
0
4
0
2
4
0
4
4
-32
+0
4
0
4
4
2
0
4
0
8
8
4
0
0
0
4
2
0
4
0
4
0
4
4
4
4
0
4
0
0
2
0
4
0
4
0
4
4
0
0
4
4
4
0
4
4
0
0
4
4
4
4
0
2
0
0
0
4
2
4
4
4
4
4
2
0
4
4
0
4
0
0
4
2
0
4
0
4
4
4
4
0
4
0
0
4
0
0
0
0
0
-64
+0
0
4
0
0
0
4
4
4
4
0
0
4
4
4
4
4
4
16
4
4
4
0
4
4
4
4
0
2
4
4
0
16
0
0
-128
+0
0
2
4
4
4
-64
+0
4
0
0
4
0
0
4
0
0
4
4
0
4
4
4
0
4
4
4
4
0
4
0
-64
+0
4
0
0
0
0
4
4
4
2
4
0
0
4
0
0
0
4
0
0
0
0
4
-32
-128
+0
+0
4
2
4
4
0
4
0
0
4
0
16
0
4
0
4
-128
+0
2
8
4
0
0
0
0
0
4
0
4
4
4
0
0
0
0
4
4
0
0
0
4
0
0
0
2
4
4
0
0
4
2
0
0
4
4
4
-64
+0
4
4
0
0
2
4
4
0
0
0
0
4
4
4
2
0
-32
+0
0
0
4
4
4
4
2
4
4
0
0
0
-64
+0
0
0
0
0
4
0
2
2
4
4
4
4
-32
+0
0
0
4
0
0
0
4
4
0
0
8
4
2
4
0
4
0
4
2
0
4
0
0
0
4
4
0
4
0
4
0
4
0
4
4
-64
+0
4
4
4
4
4
4
2
2
2
0
0
0
4
0
4
0
4
0
0
4
4
4
4
8
0
8
0
0
0
0
4
4
0
2
2
0
2
4
-32
+0
0
4
4
4
0
4
2
0
4
0
4
0
0
4
0
4
0
4
0
4
0
4
4
4
0
0
0
4
4
4
4
0
0
0
0
4
0
4
0
0
2
4
4
0
0
2
4
0
2
8
4
4
0
0
4
0
0
4
0
4
4
4
4
-32
+0
4
4
4
4
4
0
0
4
0
0
4
2
4
0
4
0
2
0
0
0
4
4
4
4
0
4
0
0
4
4
0
4
4
8
0
4
0
4
0
4
4
-128
+0
4
0
0
0
2
0
16
0
0
0
4
4
0
0
4
0
0
4
0
2
0
0
4
0
4
0
4
0
4
-64
+0
4
16
4
4
4
0
2
2
0
0
8
4
0
4
0
0
4
4
4
0
-64
+0
4
-64
-32
+0
+0
0
0
4
-32
+0
0
0
4
0
8
0
0
0
4
4
2
4
0
2
4
0
2
0
0
0
4
0
4
4
4
4
0
0
-64
+0
4
0
4
0
4
4
2
4
4
4
4
0
0
4
4
-128
+0
0
2
0
0
0
4
0
0
0
0
4
4
0
4
4
0
0
4
4
0
0
0
0
0
0
0
4
0
0
-32
+0
0
4
0
0
0
4
0
0
4
-128
+0
0
0
4
0
0
4
0
0
0
0
-64
+0
4
0
4
0
4
2
0
4
4
4
0
0
0
4
4
-32
+0
0
2
0
4
4
16
4
4
4
0
0
0
4
0
0
0
4
0
0
0
-32
+0
4
0
0
4
0
0
4
16
0
4
2
0
0
0
0
4
0
-128
+0
0
0
4
4
4
0
0
0
-32
+0
0
4
2
0
2
0
4
2
4
4
8
16
0
4
4
4
4
0
4
0
16
0
4
4
0
0
0
4
0
0
0
4
0
4
0
4
4
4
4
0
4
4
0
0
0
0
4
4
4
0
0
8
4
2
4
4
4
4
0
4
4
0
0
2
4
16
0
4
2
0
0
4
4
0
0
4
4
4
0
0
0
-32
+0
4
0
4
0
0
0
0
4
0
0
-128
+0
0
4
0
0
0
4
0
0
4
0
2
0
0
0
4
0
0
-64
+0
4
0
4
0
4
4
4
0
0
4
4
0
0
4
4
2
0
4
0
0
4
4
0
4
4
0
0
0
4
0
2
16
0
2
4
4
2
-32
+0
0
0
4
0
2
4
-64
+0
0
0
0
0
4
4
4
2
4
0
0
-32
+0
0
4
0
0
0
0
4
0
0
0
4
0
4
4
0
-64
+0
4
4
4
0
-64
+0
0
4
4
0
4
4
0
0
4
2
4
4
0
0
4
0
0
4
0
0
4
16
0
4
0
4
4
0
2
4
4
0
4
0
4
0
0
4
8
0
0
0
4
0
4
4
4
8
8
-64
+0
0
4
0
4
4
4
16
0
2
-128
+0
4
4
0
0
4
0
0
0
-64
+0
0
4
0
-64
-128
+0
+0
2
8
4
0
2
0
0
0
4
4
4
4
0
0
4
2
0
0
4
4
0
2
0
4
4
4
0
4
4
4
0
0
4
4
0
0
0
4
4
4
2
0
4
4
4
0
4
4
4
4
0
0
0
4
4
4
0
4
0
4
0
0
4
0
0
0
-64
+0
0
4
4
2
0
0
0
4
0
4
0
4
4
4
0
16
4
0
4
8
0
2
4
4
4
4
2
4
0
0
4
4
0
-32
+0
0
0
0
0
4
4
0
4
0
0
4
-64
+0
4
0
4
0
0
0
4
-32
+0
0
0
4
4
8
4
4
0
0
0
0
-64
+0
4
4
0
0
2
-32
+0
2
0
4
4
4
0
-32
+0
2
4
4
4
2
4
4
2
2
0
0
4
0
4
0
4
4
4
0
0
4
4
4
0
2
4
2
4
2
0
4
4
2
0
4
2
0
4
0
0
4
8
0
2
4
0
16
0
4
0
4
4
2
0
2
0
0
4
0
0
0
0
4
4
4
4
2
-64
+0
4
0
4
2
0
0
0
4
4
4
4
4
4
0
0
4
4
4
4
0
-64
+0
4
4
0
0
0
0
0
2
4
0
4
4
4
0
0
4
0
0
4
2
0
4
4
8
2
0
0
4
4
16
4
0
0
0
4
4
0
0
-64
+0
4
4
4
16
4
4
0
4
0
0
2
0
4
4
0
4
4
0
4
0
4
4
0
4
0
4
4
0
0
0
0
0
0
0
4
-128
+0
0
4
0
0
-128
+0
4
-128
+0
0
0
0
0
0
16
16
4
0
0
4
4
4
4
2
4
0
0
4
0
4
0
0
4
-128
+0
4
0
0
4
4
4
4
2
4
-128
0
-64
+0
+0
0
4
16
0
0
0
4
0
0
4
0
4
0
4
8
4
0
4
4
0
4
0
4
0
0
2
4
4
4
0
0
4
0
4
4
0
0
0
4
4
2
0
0
4
0
0
0
4
4
4
0
4
0
4
0
4
16
4
8
4
0
4
0
4
4
2
0
4
4
0
4
0
0
4
0
4
4
0
4
0
4
0
4
4
4
4
4
-64
+0
4
2
4
0
0
2
-32
+0
0
4
-128
+0
4
0
4
4
4
2
-64
+0
0
4
4
0
4
4
0
2
0
0
4
0
4
0
0
0
4
4
4
0
0
0
4
4
0
0
0
4
0
0
0
0
0
0
0
0
0
2
0
4
0
4
0
4
0
4
0
0
0
4
0
0
0
4
0
0
0
0
4
0
0
8
4
0
0
0
4
4
4
4
0
4
4
4
4
4
0
4
4
4
0
0
0
4
4
4
4
8
4
4
4
4
0
4
8
4
0
-64
+0
0
2
0
0
0
0
4
0
0
0
4
4
4
4
4
0
4
4
0
4
4
4
0
0
0
4
4
0
0
0
-32
+0
0
4
4
4
0
0
0
4
0
-128
+0
4
4
4
4
4
2
16
-32
+0
4
4
0
0
0
2
0
-64
+0
4
0
4
0
0
4
4
4
4
2
4
16
4
0
0
4
2
0
4
4
0
4
0
4
4
0
4
0
4
4
4
4
0
4
0
4
0
0
4
4
4
0
4
0
-64
+0
4
4
4
0
4
0
2
4
4
0
4
0
4
4
4
4
0
0
0
0
4
4
4
4
0
2
4
0
8
0
4
0
0
0
0
0
4
4
4
0
0
0
0
0
2
0
4
4
4
16
4
4
4
4
4
0
0
0
0
4
4
4
-64
+0
4
4
0
2
0
4
4
4
0
4
2
0
4
4
4
0
0
2
0
4
0
0
4
0
0
4
4
4
4
4
2
4
0
4
0
4
4
0
-64
+0
4
2
4
4
0
0
4
0
0
0
0
4
4
8
0
0
2
4
4
0
0
0
4
0
4
0
4
0
4
4
2
4
4
-128
+0
4
0
4
4
0
4
2
0
4
4
4
4
2
0
0
4
0
0
0
4
4
0
4
0
4
4
0
0
4
4
2
4
0
4
4
0
0
2
0
0
0
8
0
0
4
4
0
0
0
0
0
0
4
0
2
4
0
0
4
0
0
4
0
4
4
4
4
8
0
0
0
0
4
4
4
0
4
4
0
4
4
0
8
4
4
2
2
0
0
0
4
0
0
4
4
4
4
0
0
4
0
4
4
0
4
4
4
4
8
0
2
4
0
-64
+0
2
4
4
4
0
0
0
0
4
0
0
4
0
0
2
4
4
4
0
0
4
4
0
2
-128
+0
4
0
0
0
4
8
4
4
0
4
0
0
4
0
4
0
4
0
4
4
16
0
0
4
0
0
0
0
16
0
4
0
0
4
4
0
4
4
4
4
0
4
-64
0
-64
+0
+0
16
4
0
4
4
0
4
0
0
0
4
0
0
2
4
0
4
2
0
4
0
4
4
4
0
0
4
4
4
4
4
2
0
16
0
0
4
4
4
4
0
4
0
4
4
2
0
0
4
4
2
-32
+0
0
4
0
-128
+0
0
0
0
2
-32
+0
4
4
0
4
-64
+0
4
0
2
4
0
4
0
0
4
0
0
4
0
4
0
0
4
0
2
4
4
4
0
0
4
0
4
4
4
0
4
2
0
4
4
0
0
0
-32
+0
0
0
4
4
4
0
0
4
0
4
4
0
4
0
0
0
4
0
0
-32
+0
4
4
0
4
4
2
0
4
4
4
-64
+0
16
0
0
4
4
4
0
4
0
0
4
2
0
2
4
0
4
0
4
0
0
4
0
0
0
0
4
0
0
4
0
4
0
4
0
0
0
0
4
4
4
4
4
0
0
0
4
0
4
0
2
0
4
0
0
-64
-64
-128
+0
+0
+0
0
0
4
0
4
0
16
4
0
4
2
0
0
0
0
4
4
0
0
0
0
0
4
4
4
4
4
2
16
4
0
0
0
0
-128
+0
4
4
0
0
4
4
4
4
4
4
4
4
0
4
0
4
4
16
-128
+0
4
0
0
4
4
4
4
4
0
4
4
4
2
4
2
4
2
4
0
4
4
0
4
4
0
-32
+0
4
4
16
0
2
0
4
4
2
4
4
4
0
16
4
0
4
4
4
0
0
0
0
0
4
0
4
0
4
0
4
4
4
4
0
0
4
4
0
16
0
0
0
0
4
0
16
0
0
0
4
0
0
0
4
4
4
0
0
0
0
0
4
4
0
4
0
4
4
0
2
0
2
0
0
0
0
0
4
0
0
4
4
4
0
0
0
4
0
4
4
0
4
4
4
0
4
0
2
0
0
4
0
4
0
0
0
0
4
0
4
4
4
0
0
4
4
4
0
4
2
0
4
4
-128
+0
2
4
4
4
16
0
4
0
4
0
0
4
4
2
4
-128
+0
2
0
0
4
2
0
0
0
4
0
4
4
0
0
0
0
0
0
2
4
0
4
0
4
8
0
0
4
0
0
4
0
0
4
16
4
4
0
0
0
4
0
0
0
0
4
16
0
4
4
0
4
0
0
4
4
4
4
0
0
4
0
4
0
0
4
4
-64
+0
4
4
0
4
8
0
0
0
4
4
4
0
4
0
0
4
0
0
8
16
2
0
4
0
4
0
4
4
0
0
4
4
0
4
0
8
2
4
0
0
4
4
4
4
0
0
0
0
0
0
4
4
0
16
4
0
4
2
0
4
0
4
0
4
0
0
0
4
4
0
4
4
0
4
0
-32
+0
4
0
0
0
0
4
0
0
4
4
0
0
4
4
0
4
2
4
0
0
0
4
-64
+0
4
-128
+0
0
4
4
8
0
4
8
0
-32
+0
4
4
16
2
4
4
0
4
0
0
4
16
4
4
0
0
4
0
4
4
4
8
4
0
4
4
4
2
4
2
4
4
0
4
4
0
4
0
4
4
0
2
0
4
16
4
4
4
0
0
0
4
4
0
4
4
0
4
4
4
4
4
4
0
4
4
4
4
4
2
0
4
4
0
0
4
0
4
4
4
0
2
0
4
0
4
4
0
0
2
0
4
0
4
0
4
4
0
4
4
-128
+0
2
0
4
4
4
4
-128
+0
0
0
8
4
-32
-128
+0
+0
4
16
2
0
4
4
2
4
4
-32
+0
4
2
4
0
0
4
0
0
0
0
4
0
0
0
4
4
4
4
0
0
4
4
0
4
0
4
0
4
4
4
4
0
-128
+0
16
-32
+0
4
8
0
4
0
0
0
0
4
0
-128
+0
4
0
0
0
4
4
4
0
0
-128
+0
4
4
4
0
0
4
0
2
4
0
0
4
4
0
4
0
0
4
0
-64
+0
0
2
0
4
0
0
4
4
4
4
2
4
0
4
-64
+0
4
4
0
0
0
0
4
4
0
4
0
4
0
0
0
4
4
4
4
4
4
4
4
4
4
4
0
4
4
0
4
16
0
4
4
16
4
4
4
4
4
4
4
4
2
4
0
0
0
4
0
0
4
0
4
4
4
4
0
0
0
0
0
4
8
0
4
2
4
4
4
4
0
4
0
2
4
4
4
4
4
0
4
4
0
4
4
4
0
0
0
4
-64
+0
0
4
0
0
2
4
4
4
4
8
4
diff --git a/t/test_classify.cc b/t/test_classify.cc
index ede2728..9e3ff52 100644
--- a/t/test_classify.cc
+++ b/t/test_classify.cc
@@ -1,983 +1,991 @@
/**
* \authors The HEJ collaboration (see AUTHORS for details)
* \date 2019
* \copyright GPLv2 or later
*/
#include <iostream>
#include <random>
#include "HEJ/Event.hh"
#include "HEJ/exceptions.hh"
#define ASSERT(x) if(!(x)) { \
throw std::logic_error("Assertion '" #x "' failed."); \
}
namespace {
const fastjet::JetDefinition jet_def{fastjet::JetAlgorithm::antikt_algorithm, 0.4};
const double min_jet_pt{30.};
const std::array<std::string, 6> all_quarks{"-4","-1","1","2","3","4"};
const std::array<std::string, 7> all_partons{"g","-2","-1","1","2","3","4"};
const std::array<std::string, 3> all_bosons{"h", "Wp", "Wm"};
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));
}
}
}
// if pos_boson = -1 (or not implemented) -> no boson
// njet==7 is special: has less jets, i.e. multiple parton in one jet,
// pos_boson < 0 to select process (see list for details)
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, { -11, -18, -42, 47}, {}});
ev.outgoing.push_back({gluon, { -15, 26, -18, 35}, {}});
ev.outgoing.push_back({gluon, { 68, 87, -24, 113}, {}});
ev.outgoing.push_back({gluon, { 23, -54, -6, 59}, {}});
ev.outgoing.push_back({gluon, { -5, -44, 8, 45}, {}});
ev.outgoing.push_back({gluon, { -48, -96, 44, 116}, {}});
ev.outgoing.push_back({gluon, { -12, 99, 88, 133}, {}});
ev.incoming[0] = {gluon, { 0, 0, -249, 249}, {}};
ev.incoming[1] = {gluon, { 0, 0, 299, 299}, {}};
return ev;
case -2: // jet idx: 0 1 2 3 4 -1 -1
ev.outgoing.push_back({gluon, { 23, -80, -64, 105}, {}});
ev.outgoing.push_back({gluon, { -5, -84, -12, 85}, {}});
ev.outgoing.push_back({gluon, { 68, 87, 24, 113}, {}});
ev.outgoing.push_back({gluon, { -12, 99, 88, 133}, {}});
ev.outgoing.push_back({gluon, { -48, -24, 62, 82}, {}});
ev.outgoing.push_back({gluon, { -11, -18, 42, 47}, {}});
ev.outgoing.push_back({gluon, { -15, 20, 60, 65}, {}});
ev.incoming[0] = {gluon, { 0, 0, -215, 215}, {}};
ev.incoming[1] = {gluon, { 0, 0, 415, 415}, {}};
return ev;
case -3: // jet idx: 0 0 1 2 3 4 5
ev.outgoing.push_back({gluon, { -5, -86, -70, 111}, {}});
ev.outgoing.push_back({gluon, { -15, -52, -36, 65}, {}});
ev.outgoing.push_back({gluon, { -12, 99, -44, 109}, {}});
ev.outgoing.push_back({gluon, { -48, -60, 5, 77}, {}});
ev.outgoing.push_back({gluon, { -11, 92, 8, 93}, {}});
ev.outgoing.push_back({gluon, { 68, 87, 24, 113}, {}});
ev.outgoing.push_back({gluon, { 23, -80, 64, 105}, {}});
ev.incoming[0] = {gluon, { 0, 0, -361, 361}, {}};
ev.incoming[1] = {gluon, { 0, 0, 312, 312}, {}};
return ev;
case -4: // jet idx: 0 1 2 3 4 5 5
ev.outgoing.push_back({gluon, { -5, -40, -56, 69}, {}});
ev.outgoing.push_back({gluon, { -12, 99, -88, 133}, {}});
ev.outgoing.push_back({gluon, { 23, -84, -72, 113}, {}});
ev.outgoing.push_back({gluon, { -11, 92, 8, 93}, {}});
ev.outgoing.push_back({gluon, { 68, 87, 24, 113}, {}});
ev.outgoing.push_back({gluon, { -15, -58, 30, 67}, {}});
ev.outgoing.push_back({gluon, { -48, -96, 96, 144}, {}});
ev.incoming[0] = {gluon, { 0, 0, -395, 395}, {}};
ev.incoming[1] = {gluon, { 0, 0, 337, 337}, {}};
return ev;
case -5: // jet idx: 0 1 -1 -1 2 3 4
ev.outgoing.push_back({gluon, { 23, -64, -80, 105}, {}});
ev.outgoing.push_back({gluon, { -12, 99, -16, 101}, {}});
ev.outgoing.push_back({gluon, { -15, 20, 0, 25}, {}});
ev.outgoing.push_back({gluon, { -11, -10, 2, 15}, {}});
ev.outgoing.push_back({gluon, { 68, 87, 24, 113}, {}});
ev.outgoing.push_back({gluon, { -48, -72, 54, 102}, {}});
ev.outgoing.push_back({gluon, { -5, -60, 48, 77}, {}});
ev.incoming[0] = {gluon, { 0, 0, -253, 253}, {}};
ev.incoming[1] = {gluon, { 0, 0, 285, 285}, {}};
return ev;
case -6: // jet idx: 0 0 0 1 2 2 3
ev.outgoing.push_back({gluon, { -5, -60, -48, 77}, {}});
ev.outgoing.push_back({gluon, { -15, -52, -36, 65}, {}});
ev.outgoing.push_back({gluon, { -48, -96, -58, 122}, {}});
ev.outgoing.push_back({gluon, { 68, 87, -24, 113}, {}});
ev.outgoing.push_back({gluon, { -12, 99, -16, 101}, {}});
ev.outgoing.push_back({gluon, { -11, 92, 8, 93}, {}});
ev.outgoing.push_back({gluon, { 23, -70, 14, 75}, {}});
ev.incoming[0] = {gluon, { 0, 0, -403, 403}, {}};
ev.incoming[1] = {gluon, { 0, 0, 243, 243}, {}};
return ev;
case -7: // jet idx: 0 1 1 2 2 3 4
ev.outgoing.push_back({gluon, { 23, -46, -46, 69}, {}});
ev.outgoing.push_back({gluon, { -15, -90, -70, 115}, {}});
ev.outgoing.push_back({gluon, { -5, -78, -54, 95}, {}});
ev.outgoing.push_back({gluon, { -11, 88, -28, 93}, {}});
ev.outgoing.push_back({gluon, { -12, 99, -16, 101}, {}});
ev.outgoing.push_back({gluon, { -48, -60, 5, 77}, {}});
ev.outgoing.push_back({gluon, { 68, 87, 24, 113}, {}});
ev.incoming[0] = {gluon, { 0, 0, -424, 424}, {}};
ev.incoming[1] = {gluon, { 0, 0, 239, 239}, {}};
return ev;
case -8: // jet idx: 0 1 2 2 2 3 4
ev.outgoing.push_back({gluon, { 23, -84, -84, 121}, {}});
ev.outgoing.push_back({gluon, { -11, 92, -8, 93}, {}});
ev.outgoing.push_back({gluon, { -15, -36, 0, 39}, {}});
ev.outgoing.push_back({gluon, { -5, -62, 10, 63}, {}});
ev.outgoing.push_back({gluon, { -48, -96, 19, 109}, {}});
ev.outgoing.push_back({gluon, { 68, 87, 24, 113}, {}});
ev.outgoing.push_back({gluon, { -12, 99, 88, 133}, {}});
ev.incoming[0] = {gluon, { 0, 0, -311, 311}, {}};
ev.incoming[1] = {gluon, { 0, 0, 360, 360}, {}};
return ev;
case -9: // jet idx: 0 1 2 1 3 0 4
ev.outgoing.push_back({gluon, { -12, 99, -44, 109}, {}});
ev.outgoing.push_back({gluon, { -48, -80, -30, 98}, {}});
ev.outgoing.push_back({gluon, { 68, 87, -24, 113}, {}});
ev.outgoing.push_back({gluon, { -15, -90, -18, 93}, {}});
ev.outgoing.push_back({gluon, { 23, -70, -14, 75}, {}});
ev.outgoing.push_back({gluon, { -11, 92, -8, 93}, {}});
ev.outgoing.push_back({gluon, { -5, -38, 50, 63}, {}});
ev.incoming[0] = {gluon, { 0, 0, -366, 366}, {}};
ev.incoming[1] = {gluon, { 0, 0, 278, 278}, {}};
return ev;
case -10: // jet idx: 0 1 3 2 4 3 1
ev.outgoing.push_back({gluon, { 23, -80, -64, 105}, {}});
ev.outgoing.push_back({gluon, { -12, 99, -44, 109}, {}});
ev.outgoing.push_back({gluon, { -15, -60, -20, 65}, {}});
ev.outgoing.push_back({gluon, { -48, -54, -16, 74}, {}});
ev.outgoing.push_back({gluon, { 68, 87, -24, 113}, {}});
ev.outgoing.push_back({gluon, { -5, -84, -12, 85}, {}});
ev.outgoing.push_back({gluon, { -11, 92, -8, 93}, {}});
ev.incoming[0] = {gluon, { 0, 0, -416, 416}, {}};
ev.incoming[1] = {gluon, { 0, 0, 228, 228}, {}};
return ev;
case -11: // jet idx: 0 1 2 3 3 4 2
ev.outgoing.push_back({gluon, { -48, -56, -48, 88}, {}});
ev.outgoing.push_back({gluon, { 68, 87, -24, 113}, {}});
ev.outgoing.push_back({gluon, { -5, -62, -10, 63}, {}});
ev.outgoing.push_back({gluon, { -11, 92, 8, 93}, {}});
ev.outgoing.push_back({gluon, { -12, 99, 16, 101}, {}});
ev.outgoing.push_back({gluon, { 23, -70, 14, 75}, {}});
ev.outgoing.push_back({gluon, { -15, -90, 18, 93}, {}});
ev.incoming[0] = {gluon, { 0, 0, -326, 326}, {}};
ev.incoming[1] = {gluon, { 0, 0, 300, 300}, {}};
return ev;
case -12: // jet idx: 0 1 0 2 3 4 5
ev.outgoing.push_back({gluon, { -15, -58, -30, 67}, {}});
ev.outgoing.push_back({gluon, { 68, 87, -24, 113}, {}});
ev.outgoing.push_back({gluon, { -48, -96, -19, 109}, {}});
ev.outgoing.push_back({gluon, { 23, -54, -6, 59}, {}});
ev.outgoing.push_back({gluon, { -11, 92, -8, 93}, {}});
ev.outgoing.push_back({gluon, { -12, 99, 88, 133}, {}});
ev.outgoing.push_back({gluon, { -5, -70, 86, 111}, {}});
ev.incoming[0] = {gluon, { 0, 0, -299, 299}, {}};
ev.incoming[1] = {gluon, { 0, 0, 386, 386}, {}};
return ev;
case -13: // jet idx: 0 1 2 2 2 3 0
ev.outgoing.push_back({gluon, { -11, 88, -28, 93}, {}});
ev.outgoing.push_back({gluon, { 68, 87, -24, 113}, {}});
ev.outgoing.push_back({gluon, { -48, -84, -21, 99}, {}});
ev.outgoing.push_back({gluon, { -15, -90, -18, 93}, {}});
ev.outgoing.push_back({gluon, { -5, -30, -6, 31}, {}});
ev.outgoing.push_back({gluon, { 23, -70, -14, 75}, {}});
ev.outgoing.push_back({gluon, { -12, 99, -16, 101}, {}});
ev.incoming[0] = {gluon, { 0, 0, -366, 366}, {}};
ev.incoming[1] = {gluon, { 0, 0, 239, 239}, {}};
return ev;
}
}
throw HEJ::unknown_option{"unkown process"};
}
bool couple_quark(std::string const & boson, std::string & quark){
if(abs(HEJ::to_ParticleID(boson)) == HEJ::ParticleID::Wp){
auto qflav{ HEJ::to_ParticleID(quark) };
if(!HEJ::is_anyquark(qflav)) return false;
const int W_charge = HEJ::to_ParticleID(boson)>0?1:-1;
if(W_charge*qflav < 0 && !(abs(qflav)%2)) return false; // not anti-down
if(W_charge*qflav > 0 && (abs(qflav)%2)) return false; // not up
quark=std::to_string(qflav-W_charge);
}
return true;
}
// create event corresponding from given Configuration
// overwrite_boson to force a specific boson position, indepentent from input
// (useful for njet == 7)
HEJ::Event parse_configuration(
std::array<std::string,2> const & in, std::vector<std::string> const & out,
int const overwrite_boson = 0
){
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(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]);
}
for(size_t i=0; i<in.size(); ++i){
ev.incoming[i].type = HEJ::to_ParticleID(in[i]);
}
shuffle_particles(ev);
return ev.cluster(jet_def, min_jet_pt);
}
bool match_expectation( HEJ::event_type::EventType expected,
std::array<std::string,2> const & in, std::vector<std::string> const & out,
int const overwrite_boson = 0
){
HEJ::Event ev{parse_configuration(in,out,overwrite_boson)};
if(ev.type() != expected){
std::cerr << "Expected type " << HEJ::event_type::name(expected)
<< " but found " << HEJ::event_type::name(ev.type()) << "\n" << ev;
auto jet_idx{ ev.particle_jet_indices(ev.jets()) };
std::cout << "Particle Jet indices: ";
for(int const i: jet_idx)
std::cout << i << " ";
std::cout << std::endl;
return false;
}
return true;
}
bool check_fkl(){
using namespace HEJ;
for(std::string const & first: all_partons) // all quark flavours
for(std::string const & last: all_partons){
for(int njet=2; njet<=6; ++njet){ // all multiplicities
if(njet==5) continue;
std::array<std::string,2> base_in{first,last};
std::vector<std::string> base_out(njet, "g");
base_out.front() = first;
base_out.back() = last;
if(!match_expectation(event_type::FKL, base_in, base_out))
return false;
for(auto const & boson: all_bosons) // any boson
for(int pos=0; pos<=njet; ++pos){ // at any position
auto in{base_in};
auto out{base_out};
// change quark flavours for W
const bool couple_idx = std::uniform_int_distribution<int>{0,1}(ran);
if(!couple_quark(boson, couple_idx?out.back():out.front()))
continue;
out.insert(out.begin()+pos, boson);
if(!match_expectation(event_type::FKL, in, out))
return false;
}
}
for(int i=-3; i>-13;--i){ // extremal parton inside jet
std::array<std::string,2> base_in{first,last};
std::vector<std::string> base_out(7, "g");
base_out.front() = first;
base_out.back() = last;
if(!match_expectation(event_type::FKL, base_in, base_out, i))
return false;
}
}
return true;
}
bool check_uno(){
using namespace HEJ;
auto const b{ event_type::unob };
auto const f{ event_type::unof };
for(std::string const & uno: all_quarks) // all quark flavours
for(std::string const & fkl: all_partons){
for(int njet=3; njet<=6; ++njet){ // all multiplicities >2
if(njet==5) continue;
for(int i=0; i<2; ++i){ // forward & backwards
std::array<std::string,2> base_in;
std::vector<std::string> base_out(njet, "g");
const int uno_pos = i?1:(njet-2);
const int fkl_pos = i?(njet-1):0;
base_in[i?0:1] = uno;
base_in[i?1:0] = fkl;
base_out[uno_pos] = uno;
base_out[fkl_pos] = fkl;
auto expectation{ i?b:f };
if( !match_expectation(expectation, base_in, base_out) )
return false;
for(auto const & boson: all_bosons){ // any boson
// at any position (higgs only inside FKL chain)
int start = 0;
int end = njet;
if(to_ParticleID(boson) == pid::higgs){
start = i?(uno_pos+1):fkl_pos;
end = i?(fkl_pos+1):uno_pos;
}
for(int pos=start; pos<=end; ++pos){
auto in{base_in};
auto out{base_out};
// change quark flavours for W
const bool couple_idx = std::uniform_int_distribution<int>{0,1}(ran);
if(!couple_quark(boson, couple_idx?out[fkl_pos]:out[uno_pos]))
continue;
out.insert(out.begin()+pos, boson);
if(!match_expectation(expectation, in, out))
return false;
}
}
}
}
// test allowed jet configurations
if(!(match_expectation(f,{fkl,uno},{fkl,"g","g","g","g",uno,"g"}, -3)
&& match_expectation(b,{uno,fkl},{"g",uno,"g","g","g","g",fkl}, -4)
&& match_expectation(f,{fkl,uno},{fkl,"g","g","g","g",uno,"g"}, -5)
&& match_expectation(b,{uno,fkl},{"g",uno,"g","g","g","g",fkl}, -5)
&& match_expectation(f,{fkl,uno},{fkl,"g","g","g","g",uno,"g"}, -6)
&& match_expectation(f,{fkl,uno},{fkl,"g","g","g","g",uno,"g"}, -7)
&& match_expectation(b,{uno,fkl},{"g",uno,"g","g","g","g",fkl}, -7)
&& match_expectation(f,{fkl,uno},{fkl,"g","g","g","g",uno,"g"}, -8)
&& match_expectation(b,{uno,fkl},{"g",uno,"g","g","g","g",fkl}, -8)
&& match_expectation(b,{uno,fkl},{"g",uno,"g","g","g","g",fkl}, -9)
&& match_expectation(f,{fkl,uno},{fkl,"g","g","g","g",uno,"g"}, -10)
&& match_expectation(f,{fkl,uno},{fkl,"g","g","g","g",uno,"g"}, -11)
&& match_expectation(b,{uno,fkl},{"g",uno,"g","g","g","g",fkl}, -11)
&& match_expectation(f,{fkl,uno},{fkl,"g","g","g","g",uno,"g"}, -12)
&& match_expectation(b,{uno,fkl},{"g",uno,"g","g","g","g",fkl}, -12)
))
return false;
}
return true;
}
bool check_extremal_qqx(){
using namespace HEJ;
auto const b{ event_type::qqxexb };
auto const f{ event_type::qqxexf };
+ //! @FIXME Higgs does not implemented for qqx
+ std::array<std::string, 2> const bosons{"W+", "W-"};
for(std::string const & qqx: all_quarks) // all quark flavours
for(std::string const & fkl: all_partons){
std::string const qqx2{ std::to_string(HEJ::to_ParticleID(qqx)*-1) };
for(int njet=3; njet<=6; ++njet){ // all multiplicities >2
if(njet==5) continue;
for(int i=0; i<2; ++i){ // forward & backwards
std::array<std::string,2> base_in;
std::vector<std::string> base_out(njet, "g");
const int qqx_pos = i?0:(njet-2);
const int fkl_pos = i?(njet-1):0;
base_in[i?0:1] = "g";
base_in[i?1:0] = fkl;
base_out[fkl_pos] = fkl;
base_out[qqx_pos] = qqx;
base_out[qqx_pos+1] = qqx2;
auto expectation{ i?b:f };
- if( !match_expectation(expectation, base_in, base_out) )
- return false;
- for(auto const & boson: all_bosons){ // any boson
+ //! @FIXME pure jets does not implemented for qqx
+ // if( !match_expectation(expectation, base_in, base_out) )
+ // return false;
+ for(auto const & boson: bosons){ // all bosons
// at any position (higgs only inside FKL chain)
int start = 0;
int end = njet;
if(to_ParticleID(boson) == pid::higgs){
start = i?(qqx_pos+2):fkl_pos;
end = i?(fkl_pos+1):qqx_pos;
}
for(int pos=start; pos<=end; ++pos){
auto in{base_in};
auto out{base_out};
// change quark flavours for W
const bool couple_idx = std::uniform_int_distribution<int>{0,1}(ran);
if(couple_idx || !couple_quark(boson, out[fkl_pos]) ){
// (randomly) try couple to FKL, else fall-back to qqx
if(!couple_quark(boson, out[qqx_pos]))
couple_quark(boson, out[qqx_pos+1]);
}
out.insert(out.begin()+pos, boson);
if(!match_expectation(expectation, in, out))
return false;
}
}
}
}
// test allowed jet configurations
- if(!(match_expectation(f,{fkl,"g"},{fkl,"g","g","g","g",qqx,qqx2}, -3)
- && match_expectation(b,{"g",fkl},{qqx,qqx2,"g","g","g","g",fkl}, -4)
- && match_expectation(f,{fkl,"g"},{fkl,"g","g","g","g",qqx,qqx2}, -5)
- && match_expectation(b,{"g",fkl},{qqx,qqx2,"g","g","g","g",fkl}, -5)
- && match_expectation(f,{fkl,"g"},{fkl,"g","g","g","g",qqx,qqx2}, -6)
- && match_expectation(f,{fkl,"g"},{fkl,"g","g","g","g",qqx,qqx2}, -7)
- && match_expectation(b,{"g",fkl},{qqx,qqx2,"g","g","g","g",fkl}, -7)
- && match_expectation(f,{fkl,"g"},{fkl,"g","g","g","g",qqx,qqx2}, -8)
- && match_expectation(b,{"g",fkl},{qqx,qqx2,"g","g","g","g",fkl}, -8)
- && match_expectation(b,{"g",fkl},{qqx,qqx2,"g","g","g","g",fkl}, -9)
- && match_expectation(f,{fkl,"g"},{fkl,"g","g","g","g",qqx,qqx2}, -10)
- && match_expectation(f,{fkl,"g"},{fkl,"g","g","g","g",qqx,qqx2}, -11)
- && match_expectation(b,{"g",fkl},{qqx,qqx2,"g","g","g","g",fkl}, -11)
- && match_expectation(f,{fkl,"g"},{fkl,"g","g","g","g",qqx,qqx2}, -12)
- && match_expectation(b,{"g",fkl},{qqx,qqx2,"g","g","g","g",fkl}, -12)
- ))
- return false;
+ //! @FIXME reactive for qqx with W
+ // if(!(match_expectation(f,{fkl,"g"},{fkl,"g","g","g","g",qqx,qqx2}, -3)
+ // && match_expectation(b,{"g",fkl},{qqx,qqx2,"g","g","g","g",fkl}, -4)
+ // && match_expectation(f,{fkl,"g"},{fkl,"g","g","g","g",qqx,qqx2}, -5)
+ // && match_expectation(b,{"g",fkl},{qqx,qqx2,"g","g","g","g",fkl}, -5)
+ // && match_expectation(f,{fkl,"g"},{fkl,"g","g","g","g",qqx,qqx2}, -6)
+ // && match_expectation(f,{fkl,"g"},{fkl,"g","g","g","g",qqx,qqx2}, -7)
+ // && match_expectation(b,{"g",fkl},{qqx,qqx2,"g","g","g","g",fkl}, -7)
+ // && match_expectation(f,{fkl,"g"},{fkl,"g","g","g","g",qqx,qqx2}, -8)
+ // && match_expectation(b,{"g",fkl},{qqx,qqx2,"g","g","g","g",fkl}, -8)
+ // && match_expectation(b,{"g",fkl},{qqx,qqx2,"g","g","g","g",fkl}, -9)
+ // && match_expectation(f,{fkl,"g"},{fkl,"g","g","g","g",qqx,qqx2}, -10)
+ // && match_expectation(f,{fkl,"g"},{fkl,"g","g","g","g",qqx,qqx2}, -11)
+ // && match_expectation(b,{"g",fkl},{qqx,qqx2,"g","g","g","g",fkl}, -11)
+ // && match_expectation(f,{fkl,"g"},{fkl,"g","g","g","g",qqx,qqx2}, -12)
+ // && match_expectation(b,{"g",fkl},{qqx,qqx2,"g","g","g","g",fkl}, -12)
+ // ))
+ // return false;
}
return true;
}
bool check_central_qqx(){
using namespace HEJ;
auto const t{ event_type::qqxmid };
+ //! @FIXME Higgs does not implemented for central qqx
+ std::array<std::string, 2> const bosons{"W+", "W-"};
for(std::string const & qqx: all_quarks) // all quark flavours
for(std::string const & fkl1: all_partons)
for(std::string const & fkl2: all_partons){
std::string const qqx2{ std::to_string(HEJ::to_ParticleID(qqx)*-1) };
for(int njet=4; njet<=6; ++njet){ // all multiplicities >3
if(njet==5) continue;
for(int qqx_pos=1; qqx_pos<njet-2; ++qqx_pos){ // any qqx position
std::array<std::string,2> base_in;
std::vector<std::string> base_out(njet, "g");
base_in[0] = fkl1;
base_in[1] = fkl2;
base_out.front() = fkl1;
base_out.back() = fkl2;
base_out[qqx_pos] = qqx;
base_out[qqx_pos+1] = qqx2;
- if( !match_expectation(t, base_in, base_out) )
- return false;
- for(auto const & boson: all_bosons) // any boson
+ //! @FIXME pure jets does not implemented for central qqx
+ // if( !match_expectation(t, base_in, base_out) )
+ // return false;
+ for(auto const & boson: bosons) // any boson
for(int pos=0; pos<=njet; ++pos){ // at any position
if( to_ParticleID(boson) == pid::higgs
&& (pos==qqx_pos || pos==qqx_pos+1) )
continue;
auto in{base_in};
auto out{base_out};
// change quark flavours for W
const int couple_idx{ std::uniform_int_distribution<int>{0,2}(ran) };
// (randomly) try couple to FKL, else fall-back to qqx
if( couple_idx == 0 && couple_quark(boson, out.front()) ){}
else if( couple_idx == 1 && couple_quark(boson, out.back()) ){}
else {
if(!couple_quark(boson, out[qqx_pos]))
couple_quark(boson, out[qqx_pos+1]);
}
out.insert(out.begin()+pos, boson);
if(!match_expectation(t, in, out))
return false;
}
}
}
// test allowed jet configurations (non exhaustive collection)
- if(!(match_expectation(t,{fkl1,fkl2},{fkl1,"g",qqx,qqx2,"g","g",fkl2}, -3)
- && match_expectation(t,{fkl1,fkl2},{fkl1,"g","g",qqx,qqx2,"g",fkl2}, -3)
- && match_expectation(t,{fkl1,fkl2},{fkl1,"g","g",qqx,qqx2,"g",fkl2}, -4)
- && match_expectation(t,{fkl1,fkl2},{fkl1,qqx,qqx2,"g","g","g",fkl2}, -4)
- && match_expectation(t,{fkl1,fkl2},{fkl1,"g","g","g",qqx,qqx2,fkl2}, -5)
- && match_expectation(t,{fkl1,fkl2},{fkl1,"g","g",qqx,qqx2,"g",fkl2}, -6)
- && match_expectation(t,{fkl1,fkl2},{fkl1,"g",qqx,qqx2,"g","g",fkl2}, -7)
- && match_expectation(t,{fkl1,fkl2},{fkl1,"g","g","g",qqx,qqx2,fkl2}, -7)
- && match_expectation(t,{fkl1,fkl2},{fkl1,qqx,qqx2,"g","g","g",fkl2}, -8)
- && match_expectation(t,{fkl1,fkl2},{fkl1,"g","g","g",qqx,qqx2,fkl2}, -8)
- && match_expectation(t,{fkl1,fkl2},{fkl1,qqx,qqx2,"g","g","g",fkl2}, -9)
- && match_expectation(t,{fkl1,fkl2},{fkl1,"g",qqx,qqx2,"g","g",fkl2}, -9)
- && match_expectation(t,{fkl1,fkl2},{fkl1,"g","g",qqx,qqx2,"g",fkl2}, -10)
- && match_expectation(t,{fkl1,fkl2},{fkl1,"g","g","g",qqx,qqx2,fkl2}, -10)
- && match_expectation(t,{fkl1,fkl2},{fkl1,"g","g","g",qqx,qqx2,fkl2}, -11)
- && match_expectation(t,{fkl1,fkl2},{fkl1,"g","g",qqx,qqx2,"g",fkl2}, -12)
- && match_expectation(t,{fkl1,fkl2},{fkl1,"g","g","g",qqx,qqx2,fkl2}, -12)
- ))
- return false;
+ //! @FIXME reactive for qqx with W
+ // if(!(match_expectation(t,{fkl1,fkl2},{fkl1,"g",qqx,qqx2,"g","g",fkl2}, -3)
+ // && match_expectation(t,{fkl1,fkl2},{fkl1,"g","g",qqx,qqx2,"g",fkl2}, -3)
+ // && match_expectation(t,{fkl1,fkl2},{fkl1,"g","g",qqx,qqx2,"g",fkl2}, -4)
+ // && match_expectation(t,{fkl1,fkl2},{fkl1,qqx,qqx2,"g","g","g",fkl2}, -4)
+ // && match_expectation(t,{fkl1,fkl2},{fkl1,"g","g","g",qqx,qqx2,fkl2}, -5)
+ // && match_expectation(t,{fkl1,fkl2},{fkl1,"g","g",qqx,qqx2,"g",fkl2}, -6)
+ // && match_expectation(t,{fkl1,fkl2},{fkl1,"g",qqx,qqx2,"g","g",fkl2}, -7)
+ // && match_expectation(t,{fkl1,fkl2},{fkl1,"g","g","g",qqx,qqx2,fkl2}, -7)
+ // && match_expectation(t,{fkl1,fkl2},{fkl1,qqx,qqx2,"g","g","g",fkl2}, -8)
+ // && match_expectation(t,{fkl1,fkl2},{fkl1,"g","g","g",qqx,qqx2,fkl2}, -8)
+ // && match_expectation(t,{fkl1,fkl2},{fkl1,qqx,qqx2,"g","g","g",fkl2}, -9)
+ // && match_expectation(t,{fkl1,fkl2},{fkl1,"g",qqx,qqx2,"g","g",fkl2}, -9)
+ // && match_expectation(t,{fkl1,fkl2},{fkl1,"g","g",qqx,qqx2,"g",fkl2}, -10)
+ // && match_expectation(t,{fkl1,fkl2},{fkl1,"g","g","g",qqx,qqx2,fkl2}, -10)
+ // && match_expectation(t,{fkl1,fkl2},{fkl1,"g","g","g",qqx,qqx2,fkl2}, -11)
+ // && match_expectation(t,{fkl1,fkl2},{fkl1,"g","g",qqx,qqx2,"g",fkl2}, -12)
+ // && match_expectation(t,{fkl1,fkl2},{fkl1,"g","g","g",qqx,qqx2,fkl2}, -12)
+ // ))
+ // return false;
}
return true;
}
// this checks a (non excessive) list of non-resummable states
bool check_non_resummable(){
auto type{ HEJ::event_type::non_resummable};
return
// 2j - crossing lines
match_expectation(type, {"g","2"}, {"2","g"})
&& match_expectation(type, {"-1","g"}, {"g","-1"})
&& match_expectation(type, {"1","-1"}, {"-1","1"})
&& match_expectation(type, {"g","2"}, {"2","g","h"})
&& match_expectation(type, {"1","2"}, {"2","h","1"})
&& match_expectation(type, {"1","-1"}, {"h","-1","1"})
&& match_expectation(type, {"g","2"}, {"Wp","1","g"})
&& match_expectation(type, {"1","-1"}, {"-2","Wp","1"})
&& match_expectation(type, {"4","g"}, {"g","3","Wp"})
&& match_expectation(type, {"1","-2"}, {"-1","Wm","1"})
&& match_expectation(type, {"g","3"}, {"4","g","Wm"})
&& match_expectation(type, {"1","3"}, {"Wm","4","1"})
// 2j - qqx
&& match_expectation(type, {"g","g"}, {"1","-1"})
&& match_expectation(type, {"g","g"}, {"-2","2","h"})
&& match_expectation(type, {"g","g"}, {"-4","Wp","3"})
&& match_expectation(type, {"g","g"}, {"Wm","-1","2"})
// 3j - crossing lines
&& match_expectation(type, {"g","4"}, {"4","g","g"})
&& match_expectation(type, {"-1","g"}, {"g","g","-1"})
&& match_expectation(type, {"1","3"}, {"3","g","1"})
&& match_expectation(type, {"-2","2"}, {"2","g","-2","h"})
&& match_expectation(type, {"-3","g"}, {"g","g","Wp","-4"})
&& match_expectation(type, {"1","-2"}, {"Wm","-1","g","1"})
&& match_expectation(type, {"-1","g"}, {"1","-1","-1"})
// higgs inside uno
&& match_expectation(type, {"-1","g"}, {"g","h","-1","g"})
&& match_expectation(type, {"-1","1"}, {"g","h","-1","1"})
&& match_expectation(type, {"g","2"}, {"g","2","h","g"})
&& match_expectation(type, {"-1","1"}, {"-1","1","h","g"})
// higgs outside uno
&& match_expectation(type, {"-1","g"}, {"h","g","-1","g"})
&& match_expectation(type, {"-1","1"}, {"-1","1","g","h"})
// higgs inside qqx
&& match_expectation(type, {"g","g"}, {"-1","h","1","g","g"})
&& match_expectation(type, {"g","g"}, {"g","-1","h","1","g"})
&& match_expectation(type, {"g","g"}, {"g","g","2","h","-2"})
// higgs outside qqx
&& match_expectation(type, {"g","g"}, {"h","-1","1","g","g"})
&& match_expectation(type, {"g","g"}, {"g","g","2","-2","h"})
// 4j - two uno
&& match_expectation(type, {"-2","2"}, {"g","-2","2","g"})
&& match_expectation(type, {"1","3"}, {"g","1","h","3","g"})
&& match_expectation(type, {"1","2"}, {"g","1","3","Wp","g"})
&& match_expectation(type, {"1","-2"}, {"g","Wm","1","-1","g"})
// 4j - two gluon outside
&& match_expectation(type, {"g","4"}, {"g","4","g","g"})
&& match_expectation(type, {"1","3"}, {"1","3","h","g","g"})
&& match_expectation(type, {"1","2"}, {"1","3","g","Wp","g"})
&& match_expectation(type, {"1","-2"}, {"1","Wm","-1","g","g"})
&& match_expectation(type, {"-1","g"}, {"g","g","-1","g"})
&& match_expectation(type, {"1","3"}, {"g","g","1","3","h"})
&& match_expectation(type, {"1","2"}, {"g","g","1","Wp","3"})
&& match_expectation(type, {"1","-2"}, {"Wm","g","g","1","-1"})
// 4j - ggx+uno
&& match_expectation(type, {"g","4"}, {"1","-1","4","g"})
&& match_expectation(type, {"2","g"}, {"g","2","-3","3"})
&& match_expectation(type, {"g","4"}, {"1","-1","h","4","g"})
&& match_expectation(type, {"2","g"}, {"g","2","-3","3","h"})
&& match_expectation(type, {"g","4"}, {"Wp","1","-1","3","g"})
&& match_expectation(type, {"2","g"}, {"g","2","-4","Wp","3"})
&& match_expectation(type, {"g","4"}, {"2","Wm","-1","4","g"})
&& match_expectation(type, {"2","g"}, {"g","2","Wp","-3","4"})
// 3j - crossing+uno
&& match_expectation(type, {"1","4"}, {"g","4","1"})
&& match_expectation(type, {"1","4"}, {"4","1","g"})
&& match_expectation(type, {"1","4"}, {"g","h","4","1"})
&& match_expectation(type, {"-1","-3"},{"Wm","g","-4","-1"})
&& match_expectation(type, {"1","4"}, {"3","1","Wp","g"})
&& match_expectation(type, {"1","4"}, {"3","1","g","h"})
// 3j - crossing+qqx
&& match_expectation(type, {"1","g"}, {"-1","1","g","1"})
&& match_expectation(type, {"1","g"}, {"-1","1","1","g"})
&& match_expectation(type, {"g","1"}, {"1","g","1","-1"})
&& match_expectation(type, {"g","1"}, {"g","1","1","-1"})
&& match_expectation(type, {"1","g"}, {"2","-2","g","1"})
&& match_expectation(type, {"1","g"}, {"2","-2","1","g"})
&& match_expectation(type, {"g","1"}, {"1","g","-2","2"})
&& match_expectation(type, {"g","1"}, {"g","1","-2","2"})
&& match_expectation(type, {"1","g"}, {"-1","1","h","g","1"})
&& match_expectation(type, {"1","g"}, {"-1","h","1","1","g"})
&& match_expectation(type, {"g","1"}, {"1","g","1","h","-1"})
&& match_expectation(type, {"g","1"}, {"h","g","1","1","-1"})
&& match_expectation(type, {"1","g"}, {"2","-2","1","g","h"})
&& match_expectation(type, {"g","1"}, {"g","h","1","-2","2"})
&& match_expectation(type, {"1","g"}, {"Wp","3","-4","g","1"})
&& match_expectation(type, {"3","g"}, {"-2","Wm","1","3","g"})
&& match_expectation(type, {"g","1"}, {"1","g","Wm","-3","4"})
&& match_expectation(type, {"g","-3"}, {"g","-3","-1","Wp","2"})
// 4j- gluon in qqx
&& match_expectation(type, {"g","1"}, {"1","g","-1","1"})
&& match_expectation(type, {"1","g"}, {"1","-1","g","1"})
&& match_expectation(type, {"g","1"}, {"1","g","Wm","-2","1"})
&& match_expectation(type, {"2","g"}, {"2","-2","g","Wp","1"})
&& match_expectation(type, {"g","g"}, {"Wp","3","g","-4","g"})
&& match_expectation(type, {"1","g"}, {"1","h","-1","g","1"})
// 6j - two qqx
&& match_expectation(type, {"g","g"}, {"1","-1","g","g","1","-1"})
&& match_expectation(type, {"g","g"}, {"1","-1","g","1","-1","g"})
&& match_expectation(type, {"g","g"}, {"g","1","-1","g","1","-1"})
&& match_expectation(type, {"g","g"}, {"g","1","-1","1","-1","g"})
&& match_expectation(type, {"g","g"}, {"g","1","1","-1","-1","g"})
&& match_expectation(type, {"g","g"}, {"h","1","-1","g","g","1","-1"})
&& match_expectation(type, {"g","g"}, {"1","Wp","-2","g","1","-1","g"})
&& match_expectation(type, {"g","g"}, {"g","1","Wp","-1","g","1","-2"})
&& match_expectation(type, {"g","g"}, {"g","1","-1","Wm","2","-1","g"})
&& match_expectation(type, {"g","g"}, {"g","1","2","-1","Wm","-1","g"})
// random stuff (can be non-physical)
&& match_expectation(type, {"g","g"}, {"1","-2","2","-1"}) // != 2 qqx
&& match_expectation(type, {"g","g"}, {"1","-2","2","g"}) // could be qqx
&& match_expectation(type, {"e+","e-"},{"1","-1"}) // bad initial state
&& match_expectation(type, {"1","e-"}, {"g","1","Wm"}) // bad initial state
&& match_expectation(type, {"h","g"}, {"g","g"}) // bad initial state
&& match_expectation(type, {"-1","g"}, {"-1","1","1"}) // bad qqx
&& match_expectation(type, {"-1","g"}, {"1","1","-1"}) // crossing in bad qqx
&& match_expectation(type, {"-1","g"}, {"-2","1","1","Wp"}) // bad qqx
&& match_expectation(type, {"1","2"}, {"1","-1","g","g","g","2"}) // bad qqx
&& match_expectation(type, {"1","2"}, {"1","-1","-2","g","g","2"}) // gluon in bad qqx
&& match_expectation(type, {"g","g"}, {"-1","2","g","g"}) // wrong back qqx
&& match_expectation(type, {"g","g"}, {"g","g","2","1"}) // wrong forward qqx
&& match_expectation(type, {"g","g"}, {"g","-2","1","g"}) // wrong central qqx
;
}
// Events failing the jet requirements, e.g. qqx inside one jet
//! TODO qqx currently not allow for pure jet -> need W for qqx
bool check_illegal_jets(){
auto type{ HEJ::event_type::non_resummable};
return true
// uno backward not in jet
&& match_expectation(type, {"1","g"}, {"g","1","g","g","g","g","g"}, -1)
// & also legal uno on other side
&& match_expectation(type, {"1","1"}, {"g","1","g","g","g","1","g"}, -1)
// qqx backward not in jet
&& match_expectation(type, {"g","2"}, {"-1","1","g","g","g","g","2"}, -1)
// uno forward not in jet
&& match_expectation(type, {"3","3"}, {"3","g","g","g","g","3","g"}, -2)
// qqx backward not in jet
&& match_expectation(type, {"g","g"}, {"g","g","g","g","g","-2","2"}, -2)
// uno backward in same jet
&& match_expectation(type, {"1","g"}, {"g","1","g","g","g","g","g"}, -3)
// & also legal uno on other side
&& match_expectation(type, {"1","1"}, {"g","1","g","g","g","1","g"}, -3)
// qqx backward in same jet
&& match_expectation(type, {"g","2"}, {"-4","4","g","g","g","g","2"}, -3)
// uno forward in same jet
&& match_expectation(type, {"3","2"}, {"3","g","g","g","g","2","g"}, -4)
// qqx backward in same jet
&& match_expectation(type, {"g","g"}, {"g","g","g","g","g","-2","2"}, -4)
// central qqx not in jet
&& match_expectation(type, {"1","2"}, {"1","g","-1","1","g","g","2"}, -5)
// central qqx in same jet
&& match_expectation(type, {"1","2"}, {"1","-1","1","g","g","g","2"}, -6)
// central qqx in same jet
&& match_expectation(type, {"1","2"}, {"1","g","g","g","2","-2","2"}, -6)
// central qqx in same jet
&& match_expectation(type, {"1","2"}, {"1","-1","1","g","g","g","2"}, -7)
// central qqx in same jet
&& match_expectation(type, {"1","2"}, {"1","g","g","3","-3","g","2"}, -7)
// central qqx in same jet
&& match_expectation(type, {"g","3"}, {"g","g","-2","2","g","g","3"}, -8)
// central qqx in same jet
&& match_expectation(type, {"g","-2"}, {"g","g","g","2","-2","g","-2"}, -8)
// FKL not in own jet
&& match_expectation(type, {"1","1"}, {"1","g","g","g","g","g","1"}, -1)
&& match_expectation(type, {"g","g"}, {"g","g","g","g","g","g","g"}, -2)
&& match_expectation(type, {"1","-3"}, {"1","g","g","g","g","-3","g"}, -1)
&& match_expectation(type, {"2","g"}, {"g","2","g","g","g","g","g"}, -2)
&& match_expectation(type, {"2","g"}, {"2","g","g","g","g","2","-2"}, -1)
&& match_expectation(type, {"g","-2"}, {"4","-4","g","g","g","g","-2"}, -2)
&& match_expectation(type, {"-1","g"}, {"-1","1","-1","g","g","g","g"}, -1)
&& match_expectation(type, {"4","-3"}, {"4","g","g","1","-1","g","-3"}, -2)
// FKL in same jet
&& match_expectation(type, {"1","1"}, {"1","g","g","g","g","g","1"}, -13)
// uno in same jet as FKL
&& match_expectation(type, {"-1","1"}, {"-1","g","g","g","g","1","g"}, -9)
&& match_expectation(type, {"-1","1"}, {"g","-1","g","g","g","g","1"}, -10)
&& match_expectation(type, {"-1","1"}, {"-1","g","g","g","g","1","g"}, -13)
&& match_expectation(type, {"-1","1"}, {"g","-1","g","g","g","g","1"}, -13)
// extremal qqx in same jet as FKL
&& match_expectation(type, {"-1","g"}, {"-1","g","g","g","g","1","-1"}, -9)
&& match_expectation(type, {"g","1"}, {"1","-1","g","g","g","g","1"}, -10)
&& match_expectation(type, {"-1","g"}, {"-1","g","g","g","g","-1","1"}, -13)
&& match_expectation(type, {"g","g"}, {"g","g","g","g","g","-1","1"}, -13)
// central qqx in same jet as FKL
&& match_expectation(type,{"2","2"}, {"2","-2","2","g","g","g","2"}, -3)
&& match_expectation(type,{"-1","g"}, {"-1","g","g","g","2","-2","g"}, -4)
&& match_expectation(type,{"g","4"}, {"g","g","-4","4","g","g","4"}, -6)
&& match_expectation(type,{"g","g"}, {"g","3","-3","g","g","g","g"}, -6)
&& match_expectation(type,{"g","1"}, {"g","g","g","g","-2","2","1"}, -9)
&& match_expectation(type,{"g","g"}, {"g","1","-1","g","g","g","g"}, -10)
&& match_expectation(type,{"g","1"}, {"g","g","-2","2","g","g","1"}, -11)
&& match_expectation(type,{"g","1"}, {"g","-2","2","g","g","g","1"}, -11)
&& match_expectation(type,{"3","2"}, {"3","g","-1","1","g","g","2"}, -12)
&& match_expectation(type,{"3","-2"}, {"3","-1","1","g","g","g","-2"}, -12)
&& match_expectation(type,{"3","-2"}, {"3","-1","1","g","g","g","-2"}, -13)
;
}
// Two boson states, that are currently not implemented
bool check_bad_FS(){
auto type{ HEJ::event_type::bad_final_state};
return
match_expectation(type, {"g","g"}, {"g","h","h","g"})
&& match_expectation(type, {"g","g"}, {"h","g","h","g"})
&& match_expectation(type, {"g","-1"}, {"g","h","Wp","-2"})
&& match_expectation(type, {"-3","-1"},{"-4","g","Wp","Wp","-2"})
&& match_expectation(type, {"-4","-1"},{"-3","Wp","g","Wm","-2"})
&& match_expectation(type, {"-4","-1"},{"g","-3","Wp","Wm","-2"})
&& match_expectation(type, {"-4","-1"},{"-4","g","11","-11","-2"})
&& match_expectation(type, {"-4","-1"},{"-4","g","-13","g","-2"})
;
}
// not 2 jets
bool check_not_2_jets(){
auto type{ HEJ::event_type::no_2_jets};
return
match_expectation(type, {"g","g"}, {})
&& match_expectation(type, {"1","-1"}, {})
&& match_expectation(type, {"g","-1"}, {"-1"})
&& match_expectation(type, {"g","g"}, {"g"})
;
}
}
int main() {
// tests for "no false negatives"
// i.e. all HEJ-configurations get classified correctly
if(!check_fkl()) return EXIT_FAILURE;
if(!check_uno()) return EXIT_FAILURE;
if(!check_extremal_qqx()) return EXIT_FAILURE;
if(!check_central_qqx()) return EXIT_FAILURE;
// test for "no false positive"
// i.e. non-resummable gives non-resummable
if(!check_non_resummable()) return EXIT_FAILURE;
if(!check_illegal_jets()) return EXIT_FAILURE;
if(!check_bad_FS()) return EXIT_FAILURE;
if(!check_not_2_jets()) return EXIT_FAILURE;
return EXIT_SUCCESS;
}
diff --git a/t/test_colours.cc b/t/test_colours.cc
index a7b96c4..2217d47 100644
--- a/t/test_colours.cc
+++ b/t/test_colours.cc
@@ -1,368 +1,402 @@
/**
* \authors The HEJ collaboration (see AUTHORS for details)
* \date 2019
* \copyright GPLv2 or later
*/
#include <random>
#include <stdexcept>
#include <utility>
#include "HEJ/Constants.hh"
#include "HEJ/Event.hh"
#include "HEJ/RNG.hh"
#define ASSERT(x) if(!(x)) { \
throw std::logic_error("Assertion '" #x "' failed."); \
}
/// biased RNG to connect always to colour
class dum_rnd: public HEJ::DefaultRNG {
public:
dum_rnd() = default;
double flat() override {
return 0.;
};
};
void shuffle_particles(HEJ::Event::EventData & ev) {
static std::mt19937_64 ran{0};
// 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));
}
}
}
+std::vector<HEJ::Particle> decay_Wp( HEJ::Particle const & parent ){
+ const std::array<HEJ::ParticleID, 2> decays{ HEJ::ParticleID::e_bar,
+ HEJ::ParticleID::nu_e };
+ 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 = 0.;
+ const double cos_phi = 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;
+}
+
+HEJ::Event::EventData decay_boson( HEJ::Event::EventData ev ){
+ for( size_t i=0; i<ev.outgoing.size(); ++i ){
+ if( ev.outgoing[i].type == HEJ::ParticleID::Wp){
+ ev.decays[i] = decay_Wp(ev.outgoing[i]);
+ }
+ }
+ return ev;
+}
+
+
void dump_event(HEJ::Event const & ev){
for(auto const & in: ev.incoming()){
std::cerr << "in type=" << in.type
<< ", colour={" << (*in.colour).first
<< ", " << (*in.colour).second << "}\n";
}
for(auto const & out: ev.outgoing()){
std::cerr << "out type=" << out.type << ", colour={";
if(out.colour)
std::cerr << (*out.colour).first << ", " << (*out.colour).second;
else
std::cerr << "non, non";
std::cerr << "}\n";
}
}
/// true if colour is allowed for particle
bool correct_colour(HEJ::Particle const & part){
if(!HEJ::is_parton(part) && !part.colour) return true;
if(!part.colour) return false;
int const colour = part.colour->first;
int const anti_colour = part.colour->second;
if(part.type == HEJ::ParticleID::gluon)
return colour != anti_colour
&& colour >= HEJ::COLOUR_OFFSET
&& anti_colour >= HEJ::COLOUR_OFFSET;
if(HEJ::is_quark(part))
return anti_colour == 0 && colour >= HEJ::COLOUR_OFFSET;
return colour == 0 && anti_colour >= HEJ::COLOUR_OFFSET;
}
bool correct_colour(HEJ::Event const & ev){
if(!ev.is_leading_colour())
return false;
// some of these additional checks are also in ev.is_leading_colour()
for(auto const & part: ev.incoming()){
if(!correct_colour(part))
return false;
}
for(auto const & part: ev.outgoing()){
if(!correct_colour(part))
return false;
}
return true;
}
bool match_expected(
HEJ::Event const & ev,
std::vector<HEJ::Colour> const & expected
){
ASSERT(ev.outgoing().size()+2==expected.size());
for(size_t i=0; i<ev.incoming().size(); ++i){
ASSERT(ev.incoming()[i].colour);
if( *ev.incoming()[i].colour != expected[i])
return false;
}
for(size_t i=2; i<ev.outgoing().size()+2; ++i){
if( ev.outgoing()[i-2].colour ){
if( *ev.outgoing()[i-2].colour != expected[i] )
return false;
} else if( expected[i].first != 0 || expected[i].second != 0)
return false;
}
return true;
}
void check_event(
HEJ::Event::EventData unc_ev,
std::vector<HEJ::Colour> const & expected_colours
){
+ unc_ev = decay_boson(std::move(unc_ev));
shuffle_particles(unc_ev); // make sure incoming order doesn't matter
HEJ::Event ev{unc_ev.cluster(
fastjet::JetDefinition(fastjet::JetAlgorithm::antikt_algorithm, 0.4), 30.)
};
ASSERT(HEJ::event_type::is_resummable(ev.type()));
dum_rnd rng;
ASSERT(!ev.is_leading_colour());
ASSERT(ev.generate_colours(rng));
if(!correct_colour(ev)){
std::cerr << "Found illegal colours for event\n";
dump_event(ev);
throw std::invalid_argument("Illegal colour set");
}
if(!match_expected(ev, expected_colours)){
std::cerr << "Colours didn't match expectation. Found\n";
dump_event(ev);
std::cerr << "but expected\n";
for(auto const & col: expected_colours){
std::cerr << "colour={" << col.first << ", " << col.second << "}\n";
}
throw std::logic_error("Colours did not match expectation");
}
}
HEJ::Event::EventData reset_colour(
HEJ::Event::EventData ev, std::vector<HEJ::Colour> const & goal
){
for(size_t i=0; i<2; ++i){
ev.incoming[i].colour = goal[i];
}
for(size_t i=0; i<ev.outgoing.size(); ++i){
auto const & col_goal{ goal[i+2] };
if(col_goal.first == 0 && col_goal.second == 0)
ev.outgoing[i].colour = HEJ::optional<HEJ::Colour>{};
else
ev.outgoing[i].colour = col_goal;
}
return ev;
}
int main() {
HEJ::Event::EventData ev;
std::vector<HEJ::Colour> expected_colours(7);
- /// pure gluon
- ev.incoming[0] = { HEJ::ParticleID::gluon, { 0, 0,-427, 427}, {}};
- ev.incoming[1] = { HEJ::ParticleID::gluon, { 0, 0, 851, 851}, {}};
- ev.outgoing.push_back({ HEJ::ParticleID::gluon, { 196, 124, -82, 246}, {}});
- ev.outgoing.push_back({ HEJ::ParticleID::gluon, {-167,-184, 16, 249}, {}});
- ev.outgoing.push_back({ HEJ::ParticleID::higgs, { 197, 180, 168, 339}, {}});
- ev.outgoing.push_back({ HEJ::ParticleID::gluon, {-190, -57, 126, 235}, {}});
- ev.outgoing.push_back({ HEJ::ParticleID::gluon, { -36, -63, 196, 209}, {}});
+ /// pure gluon (they all have a mass of 4 GeV to allow decays)
+ ev.incoming[0] = { HEJ::ParticleID::gluon, { 0, 0, -205, 205}, {}};
+ ev.incoming[1] = { HEJ::ParticleID::gluon, { 0, 0, 279, 279}, {}};
+ ev.outgoing.push_back({ HEJ::ParticleID::gluon, {-15, -82, -82, 117}, {}});
+ ev.outgoing.push_back({ HEJ::ParticleID::gluon, { 68, 93, 20, 117}, {}});
+ ev.outgoing.push_back({ HEJ::ParticleID::higgs, {-30, -65, 22, 75}, {}});
+ ev.outgoing.push_back({ HEJ::ParticleID::gluon, {-12, 92, 76, 120}, {}});
+ ev.outgoing.push_back({ HEJ::ParticleID::gluon, {-11, -38, 38, 55}, {}});
expected_colours[0] = {502, 501};
expected_colours[1] = {509, 502};
expected_colours[2] = {503, 501};
expected_colours[3] = {505, 503};
expected_colours[4] = { 0, 0};
expected_colours[5] = {507, 505};
expected_colours[6] = {509, 507};
// default colours is always forbidden!
// default: swap last two (anti-)colour -> crossing
ev=reset_colour(ev, expected_colours);
std::swap(ev.outgoing[4].colour, ev.outgoing[3].colour);
check_event(ev, expected_colours);
/// last g to Qx (=> gQx -> g ... Qx)
ev.incoming[1].type = HEJ::ParticleID::d_bar;
ev.outgoing[4].type = HEJ::ParticleID::d_bar;
// => only end changes
expected_colours[1].first = 0;
expected_colours[6].first = 0;
// default: swap last two anti-colours -> last gluon colour singlet
ev=reset_colour(ev, expected_colours);
std::swap(ev.outgoing[4].colour->second, ev.outgoing[3].colour->second);
check_event(ev, expected_colours);
{
// don't overwrite
auto new_expected = expected_colours;
auto new_ev = ev;
/// uno forward (=> gQx -> g ... Qx g)
std::swap(new_ev.outgoing[3].type, new_ev.outgoing[4].type);
// => uno quarks eats colour and gluon connects to anti-colour
new_expected[5] = {0, expected_colours[3].first};
new_expected[6] = {expected_colours[0].first, expected_colours[0].first+2};
new_expected[1].second += 2; // one more anti-colour in line
// default: swap last two anti-colours -> crossing
new_ev=reset_colour(new_ev, new_expected);
std::swap(new_ev.outgoing[4].colour->second, new_ev.outgoing[3].colour->second);
check_event(new_ev, new_expected);
}
/// swap Qx <-> Q (=> gQ -> g ... Q)
ev.incoming[1].type = HEJ::ParticleID::d;
ev.outgoing[4].type = HEJ::ParticleID::d;
// => swap: colour<->anti && initial<->final
std::swap(expected_colours[1], expected_colours[6]);
std::swap(expected_colours[1].first, expected_colours[1].second);
std::swap(expected_colours[6].first, expected_colours[6].second);
// default: swap incoming <-> outgoing
ev=reset_colour(ev, expected_colours);
std::swap(ev.incoming[0].colour, ev.outgoing[0].colour);
check_event(ev, expected_colours);
/// first g to qx (=> qxQ -> qx ... Q)
ev.incoming[0].type = HEJ::ParticleID::u_bar;
ev.outgoing[0].type = HEJ::ParticleID::u_bar;
expected_colours[0] = { 0, 501};
// => shift anti-colour index one up
expected_colours[1].first -= 2;
expected_colours[5] = expected_colours[3];
expected_colours[3] = expected_colours[2];
expected_colours[2] = { 0, 502};
// default: closed qx->qx g
ev=reset_colour(ev, expected_colours);
ev.outgoing[1].colour->first = ev.outgoing[0].colour->second;
ev.outgoing[1].colour->second = ev.incoming[0].colour->second;
ev.outgoing[4].colour->first = ev.outgoing[3].colour->second;
check_event(ev, expected_colours);
{
// don't overwrite
auto new_expected = expected_colours;
auto new_ev = ev;
/// uno backward (=> qxQ -> g qx ... Q)
std::swap(new_ev.outgoing[0].type, new_ev.outgoing[1].type);
// => uno gluon connects to quark colour
new_expected[3] = expected_colours[2];
new_expected[2] = {expected_colours[0].second+2, expected_colours[0].second};
// default: Colourful Higgs
new_ev=reset_colour(new_ev, new_expected);
new_ev.outgoing[2].colour = std::make_pair(1,1);
check_event(new_ev, new_expected);
/// swap qx <-> q (=> qQ -> g q ... Q)
new_ev.incoming[0].type = HEJ::ParticleID::u;
new_ev.outgoing[1].type = HEJ::ParticleID::u;
// => swap: colour<->anti && inital<->final
std::swap(new_expected[0], new_expected[3]);
std::swap(new_expected[0].first, new_expected[0].second);
std::swap(new_expected[3].first, new_expected[3].second);
// => & connect first gluon with remaining anti-colour
new_expected[2] = {new_expected[0].first, new_expected[0].first+2};
// shift colour line one down
new_expected[1].first-=2;
new_expected[5].first-=2;
new_expected[5].second-=2;
// shift anti-colour line one up
new_expected[6].first+=2;
// default: swap 2 quarks -> disconnected
new_ev=reset_colour(new_ev, new_expected);
std::swap(new_ev.outgoing[1].colour, new_ev.outgoing[4].colour);
check_event(new_ev, new_expected);
}
{
// don't overwrite
auto new_expected = expected_colours;
auto new_ev = ev;
/// uno forward (=> qxQ -> qx ... Q g)
std::swap(new_ev.outgoing[3].type, new_ev.outgoing[4].type);
// => uno gluon connects to remaining colour
new_expected[5] = expected_colours[6];
new_expected[6] = {expected_colours[3].first+2, expected_colours[3].first};
// default: no colour on last gluon
new_ev=reset_colour(new_ev, new_expected);
new_ev.incoming[1].colour->first = new_ev.outgoing[4].colour->second;
new_ev.outgoing[4].colour = {};
check_event(new_ev, new_expected);
}
{
// don't overwrite
auto new_expected = expected_colours;
auto new_ev = ev;
- /// qqx backward (=> gQ -> qx q ... Q)
+ /// qqx backward (=> gQ -> qx q ... Q) with Wp
// => swap: incoming q <-> outgoing gluon
std::swap(new_ev.incoming[0].type, new_ev.outgoing[1].type);
new_ev.outgoing[1].type=static_cast<HEJ::ParticleID>(
- -1*new_ev.outgoing[1].type);
+ -(new_ev.outgoing[1].type+1) );
+ new_ev.outgoing[2].type = HEJ::ParticleID::Wp;
// incoming q -> outgoing q (colour<->anti)
std::swap(new_expected[0], new_expected[3]);
std::swap(new_expected[3].first, new_expected[3].second);
new_expected[3].first+=2;
new_expected[0].first-=1; // skip one index
// couple first in to first out
new_expected[2].second=new_expected[0].second;
// default: swap qqx <-> first g
new_ev=reset_colour(new_ev, new_expected);
std::swap(new_ev.outgoing[0].colour->second, new_ev.outgoing[3].colour->second);
std::swap(new_ev.outgoing[1].colour->first, new_ev.outgoing[3].colour->first);
check_event(new_ev, new_expected);
}
{
// don't overwrite
auto new_expected = expected_colours;
auto new_ev = ev;
- /// qqx forward (=> qx g -> qx ... Qx Q)
+ /// qqx forward (=> qx g -> qx ... Qx Q) with Wp
// => swap: incoming Q <-> outgoing gluon
std::swap(new_ev.incoming[1].type, new_ev.outgoing[3].type);
new_ev.outgoing[3].type=static_cast<HEJ::ParticleID>(
- -1*new_ev.outgoing[3].type);
+ -(new_ev.outgoing[3].type+1));
+ new_ev.outgoing[2].type = HEJ::ParticleID::Wp;
// incoming q -> outgoing q (colour<->anti)
std::swap(new_expected[1], new_expected[5]);
std::swap(new_expected[5].first, new_expected[5].second);
new_expected[5].second-=2;
new_expected[1].second-=1; // skip one index
// couple last in to last out
new_expected[6].first=new_expected[1].first;
// default: uncoloured quark
new_ev=reset_colour(new_ev, new_expected);
new_ev.outgoing[0].colour = {};
check_event(new_ev, new_expected);
// move Higgs to position 1 (=> qx g -> qx h g Qx Q)
std::swap(new_ev.outgoing[1].type, new_ev.outgoing[2].type);
std::swap(new_expected[3], new_expected[4]); // trivial
// default: incoming qx wrong colour
new_ev=reset_colour(new_ev, new_expected);
new_ev.incoming[0].colour->first = 1;
check_event(new_ev, new_expected);
// central qqx (=> qx g -> qx h Q Qx g)
// => swap: Q <-> g
std::swap(new_ev.outgoing[2].type, new_ev.outgoing[4].type);
std::swap(new_expected[4], new_expected[6]);
// gluon was connected on left side, i.e. doesn't matter for QQx
// => couple Q to out qx
new_expected[4].first = new_expected[2].second;
// Qx next in line
new_expected[5].second = new_expected[4].first+2;
// incoming g shifted by one position in line
new_expected[1].first-=2;
new_expected[1].second+=2;
// default: wrong colour in last incoming
new_ev=reset_colour(new_ev, new_expected);
std::swap(new_ev.incoming[1].colour->first,
new_ev.incoming[1].colour->second);
check_event(new_ev, new_expected);
}
return EXIT_SUCCESS;
}
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Tue, Nov 19, 4:49 PM (1 d, 10 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
3788563
Default Alt Text
(112 KB)
Attached To
rHEJ HEJ
Event Timeline
Log In to Comment