cepgen
is hosted by
Hepforge
,
IPPP Durham
CepGen
1.2.5
Central exclusive processes event generator
Loading...
Searching...
No Matches
HepMC3EventInterface.cpp
Go to the documentation of this file.
1
/*
2
* CepGen: a central exclusive processes event generator
3
* Copyright (C) 2022-2024 Laurent Forthomme
4
*
5
* This program is free software: you can redistribute it and/or modify
6
* it under the terms of the GNU General Public License as published by
7
* the Free Software Foundation, either version 3 of the License, or
8
* any later version.
9
*
10
* This program is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
* GNU General Public License for more details.
14
*
15
* You should have received a copy of the GNU General Public License
16
* along with this program. If not, see <http://www.gnu.org/licenses/>.
17
*/
18
19
#include <HepMC3/FourVector.h>
20
#include <HepMC3/GenEvent.h>
21
#include <HepMC3/GenParticle.h>
22
#include <HepMC3/GenRunInfo.h>
23
#include <HepMC3/GenVertex.h>
24
#include <HepMC3/Version.h>
25
26
#include <list>
27
#include <numeric>
28
29
#include "
CepGen/Core/Exception.h
"
30
#include "
CepGen/Event/Event.h
"
31
#include "
CepGen/Physics/Constants.h
"
32
#include "
CepGen/Physics/PDG.h
"
33
#include "
CepGen/Utils/Collections.h
"
34
#include "
CepGenAddOns/HepMC3Wrapper/HepMC3EventInterface.h
"
35
36
namespace
HepMC3
{
37
CepGenEvent::CepGenEvent
(
const
cepgen::Event
& evt) : GenEvent(Units::GEV, Units::MM) {
38
add_attribute(
"AlphaQCD"
, make_shared<DoubleAttribute>(evt.
metadata
(
"alphaS"
)));
39
add_attribute(
"AlphaEM"
, make_shared<DoubleAttribute>(evt.
metadata
(
"alphaEM"
)));
40
41
weights().push_back(1.);
// unweighted events
42
43
// filling the particles content
44
const
FourVector origin(0., 0., 0., 0.);
45
int
cm_id = 0;
46
47
auto
v1 = make_shared<GenVertex>(origin), v2 = make_shared<GenVertex>(origin), vcm = make_shared<GenVertex>(origin);
48
unsigned
short
idx = 0;
49
for
(
const
auto
& part_orig : evt.
particles
()) {
50
const
auto
& mom_orig = part_orig.momentum();
51
FourVector pmom(mom_orig.px(), mom_orig.py(), mom_orig.pz(), mom_orig.energy());
52
auto
part = make_shared<GenParticle>(pmom, part_orig.integerPdgId(), (
int
)part_orig.status());
53
part->set_generated_mass(
cepgen::PDG::get
().mass(part_orig.pdgId()));
54
assoc_map_[idx] = part;
55
56
switch
(part_orig.role()) {
57
case
cepgen::Particle::IncomingBeam1
:
58
v1->add_particle_in(part);
59
break
;
60
case
cepgen::Particle::IncomingBeam2
:
61
v2->add_particle_in(part);
62
break
;
63
case
cepgen::Particle::OutgoingBeam1
:
64
v1->add_particle_out(part);
65
break
;
66
case
cepgen::Particle::OutgoingBeam2
:
67
v2->add_particle_out(part);
68
break
;
69
case
cepgen::Particle::Parton1
:
70
v1->add_particle_out(part);
71
vcm->add_particle_in(part);
72
break
;
73
case
cepgen::Particle::Parton2
:
74
v2->add_particle_out(part);
75
vcm->add_particle_in(part);
76
break
;
77
case
cepgen::Particle::Intermediate
:
78
// skip the two-parton system and propagate the parentage
79
cm_id = idx;
80
continue
;
81
case
cepgen::Particle::CentralSystem
:
82
default
: {
83
const
auto
& moth = part_orig.mothers();
84
if
(moth.empty())
85
// skip disconnected lines
86
continue
;
87
// get mother(s) id(s)
88
const
short
m1 = *moth.begin();
89
const
short
m2 = moth.size() > 1 ? *moth.rbegin() : -1;
90
// check if particle is connected to the two-parton system
91
if
(m1 == cm_id || (m2 >= 0 && (m1 < cm_id && cm_id <= m2)))
// also supports range
92
vcm->add_particle_out(part);
93
// if part of the decay chain of central system, find parents
94
else
if
(assoc_map_.count(m1) != 0) {
95
auto
vprod = assoc_map_.at(m1)->end_vertex();
96
std::list<short> ids{m1};
// list of mother particles
97
if
(assoc_map_.count(m2) != 0 && m2 > m1) {
98
ids.resize(m2 - m1 + 1);
99
std::iota(ids.begin(), ids.end(), m1);
100
}
101
if
(!vprod) {
102
vprod = make_shared<GenVertex>();
103
for
(
const
auto
&
id
: ids)
104
vprod->add_particle_in(assoc_map_.at(
id
));
105
add_vertex(vprod);
106
}
107
vprod->add_particle_out(part);
108
}
else
109
throw
CG_FATAL
(
"HepMC3:fillEvent"
) <<
"Other particle requested! Not yet implemented!"
;
110
}
break
;
111
}
112
idx++;
113
}
114
add_vertex(v1);
115
add_vertex(v2);
116
add_vertex(vcm);
117
}
118
119
std::ostream&
operator<<
(std::ostream& os,
const
FourVector& vec) {
120
return
os <<
"("
<< vec.x() <<
", "
<< vec.y() <<
", "
<< vec.z() <<
"; "
<< vec.t() <<
")"
;
121
}
122
123
CepGenEvent::operator
cepgen::Event
()
const
{
124
cepgen::Event
evt;
125
auto
convert_particle = [](
const
GenParticle& part,
126
const
cepgen::Particle::Role
& role =
127
cepgen::Particle::Role::UnknownRole
) ->
cepgen::Particle
{
128
auto
convert_momentum = [](
const
FourVector& mom) ->
cepgen::Momentum
{
129
return
cepgen::Momentum::fromPxPyPzE
(mom.px(), mom.py(), mom.pz(), mom.e());
130
};
131
auto
cg_part =
cepgen::Particle
(role, 0, (
cepgen::Particle::Status
)part.status());
132
cg_part.setPdgId((
long
)part.pdg_id());
133
cg_part.setMomentum(convert_momentum(part.momentum()));
134
return
cg_part;
135
};
136
137
auto
ip1 = beams().at(0), ip2 = beams().at(1);
138
std::unordered_map<size_t, size_t> h_to_cg;
139
std::vector<int> beam_vtx_ids;
140
for
(
const
auto
& vtx : vertices()) {
141
if
(vtx->particles_in().size() == 1) {
142
auto
role1 =
cepgen::Particle::Role::UnknownRole
, role2 = role1, role3 = role1;
143
auto
status1 =
cepgen::Particle::Status::PrimordialIncoming
, status2 =
cepgen::Particle::Status::Incoming
,
144
status3 =
cepgen::Particle::Status::Unfragmented
;
145
size_t
id_beam_in = 0;
146
if
(
auto
& part = vtx->particles_in().at(0); part) {
147
if
(part->id() == ip1->id()) {
148
role1 =
cepgen::Particle::IncomingBeam1
;
149
role2 =
cepgen::Particle::Parton1
;
150
role3 =
cepgen::Particle::OutgoingBeam1
;
151
}
else
if
(part->id() == ip2->id()) {
152
role1 =
cepgen::Particle::IncomingBeam2
;
153
role2 =
cepgen::Particle::Parton2
;
154
role3 =
cepgen::Particle::OutgoingBeam2
;
155
}
156
auto
cg_part = convert_particle(*part, role1);
157
cg_part.setStatus(status1);
158
evt.
addParticle
(cg_part);
159
h_to_cg[part->id()] = cg_part.id();
160
id_beam_in = cg_part.id();
161
}
162
if
(vtx->particles_out_size() == 2) {
//FIXME handle cases with multiple partons?
163
size_t
num_op = 0;
164
for
(
auto
op : vtx->particles_out()) {
165
auto
cg_part = convert_particle(*op, num_op == 0 ? role2 : role3);
166
cg_part.setStatus(num_op == 0 ? status2 : status3);
167
cg_part.addMother(evt[id_beam_in]);
168
evt.
addParticle
(cg_part);
169
h_to_cg[op->id()] = cg_part.id();
170
++num_op;
171
}
172
}
173
beam_vtx_ids.emplace_back(vtx->id());
174
}
175
}
176
177
auto
cg_interm =
cepgen::Particle
(
cepgen::Particle::Role::Intermediate
, 0,
cepgen::Particle::Status::Propagator
);
178
auto
&part1 = evt.
oneWithRole
(
cepgen::Particle::Role::Parton1
),
179
&part2 = evt.
oneWithRole
(
cepgen::Particle::Role::Parton2
);
180
cg_interm.
setMomentum
(part1.momentum() + part2.momentum(),
true
);
181
cg_interm.
addMother
(part1);
182
cg_interm.
addMother
(part2);
183
evt.
addParticle
(cg_interm);
184
185
for
(
const
auto
& vtx : vertices()) {
186
if
(
cepgen::utils::contains
(beam_vtx_ids, vtx->id()))
187
continue
;
188
for
(
auto
op : vtx->particles_out()) {
189
auto
cg_part = convert_particle(*op,
cepgen::Particle::Role::CentralSystem
);
190
cg_part.addMother(evt.
oneWithRole
(
cepgen::Particle::Role::Intermediate
));
191
evt.
addParticle
(cg_part);
192
h_to_cg[op->id()] = cg_part.id();
193
}
194
}
195
return
evt;
196
}
197
198
void
CepGenEvent::merge
(
cepgen::Event
& evt)
const
{
199
// set of sanity checks to perform on the HepMC event content
200
if
(vertices().size() < 3) {
201
CG_ERROR
(
"HepMC3:CepGenEvent:merge"
) <<
"Failed to retrieve the three primordial vertices in event."
;
202
return
;
203
}
204
const
auto
v1 = vertices().at(0), v2 = vertices().at(1), vcm = vertices().at(2);
205
if
(v1->particles_in().size() != 1) {
206
CG_ERROR
(
"HepMC3:CepGenEvent:merge"
) <<
"Invalid first incoming beam particles multiplicity: found "
207
<< v1->particles_in().size() <<
", expecting one."
;
208
return
;
209
}
210
if
(v2->particles_in().size() != 1) {
211
CG_ERROR
(
"HepMC3:CepGenEvent:merge"
) <<
"Invalid second incoming beam particles multiplicity: found "
212
<< v2->particles_in().size() <<
", expecting one."
;
213
return
;
214
}
215
// set of sanity checks to ensure the compatibility between the HepMC and CepGen event records
216
const
auto
ip1 = v1->particles_in().at(0), ip2 = v2->particles_in().at(0);
217
const
auto
&cg_ip1 = evt.
oneWithRole
(
cepgen::Particle::Role::IncomingBeam1
),
218
&cg_ip2 = evt.
oneWithRole
(
cepgen::Particle::Role::IncomingBeam2
);
219
if
(ip1->momentum().x() != cg_ip1.momentum().px() || ip1->momentum().y() != cg_ip1.momentum().py() ||
220
ip1->momentum().z() != cg_ip1.momentum().pz() || ip1->momentum().t() != cg_ip1.momentum().energy()) {
221
CG_ERROR
(
"HepMC3:CepGenEvent:merge"
) <<
"Invalid first incoming beam particle kinematics."
;
222
return
;
223
}
224
if
(ip2->momentum().x() != cg_ip2.momentum().px() || ip2->momentum().y() != cg_ip2.momentum().py() ||
225
ip2->momentum().z() != cg_ip2.momentum().pz() || ip2->momentum().t() != cg_ip2.momentum().energy()) {
226
CG_ERROR
(
"HepMC3:CepGenEvent:merge"
) <<
"Invalid second incoming beam particle kinematics."
;
227
return
;
228
}
229
auto
cs = evt[
cepgen::Particle::Role::CentralSystem
];
230
if
(cs.size() != (
size_t
)vcm->particles_out().size()) {
231
CG_ERROR
(
"HepMC3:CepGenEvent:merge"
)
232
<<
"Central system particles multiplicities differ between CepGen and HepMC3 event records."
;
233
return
;
234
}
235
// freeze the "primordial" central system size
236
const
auto
cs_size = cs.size();
237
238
// helper function to browse particles decay products and store them into the CepGen event content
239
std::function<void(
const
ConstGenParticlePtr& hp,
cepgen::ParticleRef
cp)> browse_children =
240
[&](
const
ConstGenParticlePtr& hp,
cepgen::ParticleRef
cp) {
241
if
(hp->children().empty())
242
return
;
243
cp.get().setStatus(
cepgen::Particle::Status::Propagator
);
244
for
(
const
auto
& h_child : hp->children()) {
245
cepgen::Particle
cg_child(cp.get().role(), 0);
246
cg_child.
setPdgId
((
long
)h_child->pdg_id());
247
const
auto
& c_mom = h_child->
momentum
();
248
cg_child.
setStatus
(
cepgen::Particle::Status::FinalState
);
249
cg_child.
setMomentum
(
cepgen::Momentum::fromPxPyPzE
(c_mom.x(), c_mom.y(), c_mom.z(), c_mom.t()));
250
cg_child.
addMother
(cp);
251
browse_children(h_child, evt.
addParticle
(cg_child));
252
}
253
};
254
255
for
(
size_t
icg = 0; icg < cs_size; ++icg) {
// try to find the associated CepGen event particle
256
const
auto
cg_cp_mom3 = cs[icg].get().momentum().p();
257
for
(
const
auto
& h_cp : vcm->particles_out()) {
// loop over the central system particles
258
if
(fabs(cg_cp_mom3 - h_cp->momentum().length()) > 1.e-10)
259
continue
;
260
// found the association between the HepMC and CepGen particles kinematics
261
browse_children(h_cp, cs[icg]);
262
break
;
263
}
264
}
265
}
266
267
void
CepGenEvent::dump
()
const
{
268
CG_LOG
.log([&](
auto
& log) {
269
log <<
"HepMC3::CepGenEvent\n"
270
<<
" Attributes:\n"
;
271
for
(
const
auto
& attr : {
"AlphaEM"
,
"AlphaQCD"
})
272
log <<
" * "
<< attr <<
" = "
<< attribute_as_string(attr) <<
"\n"
;
273
log <<
" Vertices:"
;
274
for
(
const
auto
& vtxPtr : vertices()) {
275
FourVector in_sys, out_sys;
276
log <<
"\n * vertex#"
<< (-vtxPtr->id()) <<
" (status: "
<< vtxPtr->status() <<
")"
277
<<
"\n in: "
;
278
for
(
const
auto
& ipPtr : vtxPtr->particles_in())
279
log <<
"\n * "
<< ipPtr->pdg_id() <<
" (status: "
<< ipPtr->status() <<
"): "
<< ipPtr->momentum(),
280
in_sys += ipPtr->momentum();
281
log <<
"\n total: "
<< in_sys <<
"\n out:"
;
282
for
(
const
auto
& opPtr : vtxPtr->particles_out())
283
log <<
"\n * "
<< opPtr->pdg_id() <<
" (status: "
<< opPtr->status() <<
"): "
<< opPtr->momentum(),
284
out_sys += opPtr->momentum();
285
const
auto
imbal = in_sys - out_sys;
286
log <<
"\n total: "
<< out_sys <<
"\n (im)balance: "
<< imbal <<
" (norm: "
<< imbal.length() <<
")."
;
287
}
288
log <<
"\n"
<< std::string(70,
'-'
);
289
});
290
}
291
}
// namespace HepMC3
Collections.h
Constants.h
Event.h
Exception.h
CG_FATAL
#define CG_FATAL(mod)
Definition
Exception.h:61
CG_ERROR
#define CG_ERROR(mod)
Definition
Exception.h:60
HepMC3EventInterface.h
CG_LOG
#define CG_LOG
Definition
Message.h:212
PDG.h
HepMC3::CepGenEvent::merge
void merge(cepgen::Event &) const
Merge this event with another CepGen event record.
Definition
HepMC3EventInterface.cpp:198
HepMC3::CepGenEvent::CepGenEvent
CepGenEvent(const cepgen::Event &)
Construct an event interface from a CepGen Event object.
Definition
HepMC3EventInterface.cpp:37
HepMC3::CepGenEvent::dump
void dump() const
Write the event content in the standard stream.
Definition
HepMC3EventInterface.cpp:267
cepgen::Event
Container for the information on the in- and outgoing particles' kinematics.
Definition
Event.h:28
cepgen::Event::oneWithRole
Particle & oneWithRole(Particle::Role role)
First Particle object with a given role in the event.
Definition
Event.cpp:190
cepgen::Event::addParticle
ParticleRef addParticle(Particle &part, bool replace=false)
Set the information on one particle in the process.
Definition
Event.cpp:323
cepgen::Event::particles
Particles particles() const
Vector of all particles in the event.
Definition
Event.cpp:353
cepgen::Event::metadata
EventMetadata metadata
List of auxiliary information.
Definition
Event.h:136
cepgen::Momentum
Container for a particle's 4-momentum, along with useful methods to ease the development of any matri...
Definition
Momentum.h:33
cepgen::Momentum::fromPxPyPzE
static Momentum fromPxPyPzE(double px, double py, double pz, double e)
Build a 4-momentum from its four momentum and energy coordinates.
Definition
Momentum.cpp:82
cepgen::PDG::get
static PDG & get()
Retrieve a unique instance of this particles info collection.
Definition
PDG.cpp:41
cepgen::Particle
Kinematic information for one particle.
Definition
Particle.h:33
cepgen::Particle::momentum
Momentum & momentum()
Retrieve the momentum object associated with this particle Retrieve the momentum object associated wi...
Definition
Particle.h:123
cepgen::Particle::setMomentum
Particle & setMomentum(const Momentum &, bool offshell=false)
Associate a momentum object to this particle.
Definition
Particle.cpp:77
cepgen::Particle::addMother
Particle & addMother(Particle &part)
Set the mother particle.
Definition
Particle.cpp:47
cepgen::Particle::Status
Status
Internal status code for a particle.
Definition
Particle.h:36
cepgen::Particle::Status::PrimordialIncoming
@ PrimordialIncoming
Incoming beam particle.
cepgen::Particle::Status::Incoming
@ Incoming
Incoming parton.
cepgen::Particle::Status::FinalState
@ FinalState
Stable, final state particle.
cepgen::Particle::Status::Unfragmented
@ Unfragmented
Particle to be hadronised externally.
cepgen::Particle::Status::Propagator
@ Propagator
Generic propagator.
cepgen::Particle::Role
Role
Definition
Particle.h:50
cepgen::Particle::IncomingBeam2
@ IncomingBeam2
incoming beam particle
Definition
Particle.h:53
cepgen::Particle::Parton2
@ Parton2
beam incoming parton
Definition
Particle.h:59
cepgen::Particle::OutgoingBeam1
@ OutgoingBeam1
outgoing beam state/particle
Definition
Particle.h:54
cepgen::Particle::UnknownRole
@ UnknownRole
Undefined role.
Definition
Particle.h:51
cepgen::Particle::IncomingBeam1
@ IncomingBeam1
incoming beam particle
Definition
Particle.h:52
cepgen::Particle::OutgoingBeam2
@ OutgoingBeam2
outgoing beam state/particle
Definition
Particle.h:55
cepgen::Particle::Parton1
@ Parton1
beam incoming parton
Definition
Particle.h:58
cepgen::Particle::CentralSystem
@ CentralSystem
Central particles system.
Definition
Particle.h:56
cepgen::Particle::Intermediate
@ Intermediate
Intermediate two-parton system.
Definition
Particle.h:57
cepgen::Particle::setStatus
Particle & setStatus(Status status)
Definition
Particle.h:96
cepgen::Particle::setPdgId
Particle & setPdgId(pdgid_t pdg, short ch=0)
Set the PDG identifier (along with the particle's electric charge)
Definition
Particle.cpp:93
HepMC3
Definition
HepMC3EventInterface.cpp:36
HepMC3::operator<<
std::ostream & operator<<(std::ostream &os, const FourVector &vec)
Definition
HepMC3EventInterface.cpp:119
cepgen::utils::contains
bool contains(const std::vector< T > &coll, const T &item)
Check if a vector contains an item.
Definition
Collections.h:47
cepgen::ParticleRef
std::reference_wrapper< Particle > ParticleRef
Reference to a Particle object.
Definition
Particle.h:168
CepGenAddOns
HepMC3Wrapper
HepMC3EventInterface.cpp
Generated on Mon Jul 29 2024 for CepGen by
1.9.7