19#include "HepMC3/ReaderFactory.h"
20#include "HepMC3/GenEvent.h"
21#include "HepMC3/GenParticle.h"
22#include "HepMC3/GenVertex.h"
23#include "HepMC3/FourVector.h"
24#include "HepMC3/Version.h"
27#include <fairlogger/Logger.h>
28#include "FairPrimaryGenerator.h"
52 mEvent =
new HepMC3::GenEvent();
62 LOG(info) <<
"Destructing GeneratorHepMC";
97 if (not
param.fileName.empty()) {
98 LOG(warn) <<
"The use of the key \"HepMC.fileName\" is "
99 <<
"deprecated, use \"GeneratorFileOrCmd.fileNames\" instead";
103 if (not
param.fileName.empty()) {
116 if (
param.version != 0 and
mCmd.empty()) {
117 LOG(warn) <<
"The key \"HepMC.version\" is no longer needed when "
118 <<
"reading from files. The format version of the input files "
119 <<
"are automatically deduced. However, it is mandatory when reading "
120 <<
"from a pipe containing HepMC2 data.";
129 if (not
param.fileName.empty()) {
130 LOG(warn) <<
"The use of the key \"HepMC.fileName\" is "
131 <<
"deprecated, use \"GeneratorFileOrCmd.fileNames\" instead";
135 if (not
param.fileName.empty()) {
148 if (
param.version != 0 and
mCmd.empty()) {
149 LOG(warn) <<
"The key \"HepMC.version\" is no longer needed when "
150 <<
"reading from files. The format version of the input files "
151 <<
"are automatically deduced. However, it is mandatory when reading "
152 <<
"from a pipe containing HepMC2 data.";
159 LOG(
debug) <<
"Generating an event";
162 constexpr int max_tries = 3;
174 mEvent->set_units(HepMC3::Units::GEV, HepMC3::Units::MM);
178 LOG(error) <<
"Event reading from HepMC failed ...";
181 }
while (tries < max_tries);
183 LOG(error) <<
"HepMC event gen failed (Does the file/stream have enough events)?";
192 HepMC3::GenEvent&
event = *
mEvent;
194 auto particles =
event.particles();
195 auto vertices =
event.vertices();
196 std::list<HepMC3::GenParticlePtr> toRemove;
198 LOG(
debug) <<
"HepMC events has " << particles.size()
199 <<
" particles and " << vertices.size()
200 <<
" vertices" << std::endl;
203 for (
size_t i = 0;
i < particles.size(); ++
i) {
204 auto particle = particles[
i];
211 toRemove.push_back(particle);
212 LOG(
debug) <<
" Remove " << std::setw(3) << particle->id();
214 auto endVtx = particle->end_vertex();
215 auto prdVtx = particle->production_vertex();
218 endVtx->remove_particle_in(particle);
219 LOG(
debug) <<
" end " << std::setw(3) << endVtx->id();
221 if (prdVtx and prdVtx->id() != endVtx->id()) {
222 auto outbound = endVtx->particles_out();
223 auto inbound = endVtx->particles_in();
224 LOG(
debug) <<
" prd " << std::setw(3) << prdVtx->id() <<
" "
225 << std::setw(3) << outbound.size() <<
" out "
227 << std::setw(3) << inbound.size() <<
" in ";
231 for (
auto outgoing : outbound) {
235 auto ee = outgoing->end_vertex();
236 if (not ee or ee->id() != prdVtx->id()) {
237 prdVtx->add_particle_out(outgoing);
239 LOG(
debug) <<
" " << std::setw(3) << outgoing->id();
246 for (
auto incoming : inbound) {
248 auto pp = incoming->production_vertex();
249 if (not pp or pp->id() != prdVtx->id()) {
250 prdVtx->add_particle_in(incoming);
253 LOG(
debug) <<
" " << std::setw(3) << incoming->id();
259 prdVtx->remove_particle_out(particle);
263 LOG(
debug) <<
"Selected " << nSelect <<
" particles\n"
264 <<
"Removing " << toRemove.size() <<
" particles";
265 size_t oldSize = particles.size();
266 for (
auto particle : toRemove) {
267 event.remove_particle(particle);
270 std::list<HepMC3::GenVertexPtr> remVtx;
271 for (
auto vtx :
event.vertices()) {
273 (vtx->particles_out().empty() and
274 vtx->particles_in().empty())) {
275 remVtx.push_back(vtx);
278 LOG(
debug) <<
"Removing " << remVtx.size() <<
" vertexes";
279 for (
auto vtx : remVtx) {
280 event.remove_vertex(vtx);
283 LOG(
debug) <<
"HepMC events was pruned from " << oldSize
284 <<
" particles to " <<
event.particles().size()
285 <<
" particles and " <<
event.vertices().size()
295 auto select = [](HepMC3::ConstGenParticlePtr particle) {
296 switch (particle->status()) {
311 auto particles =
mEvent->particles();
312 for (
int i = 0;
i < particles.size(); ++
i) {
315 auto particle = particles.at(
i);
316 auto momentum = particle->momentum();
317 auto vertex = particle->production_vertex()->position();
318 auto parents = particle->parents();
319 auto children = particle->children();
322 auto m1 = parents.empty() ? -1 : parents.front()->id() - 1;
323 auto m2 = parents.empty() ? -1 : parents.back()->id() - 1;
326 auto d1 = children.empty() ? -1 : children.front()->id() - 1;
327 auto d2 = children.empty() ? -1 : children.back()->id() - 1;
330 mParticles.push_back(TParticle(particle->pid(),
346 particle->status() == 1);
356template <
typename AttributeType,
typename TargetType>
358 const std::string&
name,
359 const std::shared_ptr<HepMC3::Attribute>&
a)
361 if (
auto* p =
dynamic_cast<AttributeType*
>(
a.get())) {
362 eventHeader->
putInfo<TargetType>(
name, p->value());
369 const std::string&
name,
370 const std::shared_ptr<HepMC3::Attribute>&
a)
372 using IntAttribute = HepMC3::IntAttribute;
373 using LongAttribute = HepMC3::LongAttribute;
374 using FloatAttribute = HepMC3::FloatAttribute;
375 using DoubleAttribute = HepMC3::DoubleAttribute;
376 using StringAttribute = HepMC3::StringAttribute;
377 using CharAttribute = HepMC3::CharAttribute;
378 using LongLongAttribute = HepMC3::LongLongAttribute;
379 using LongDoubleAttribute = HepMC3::LongDoubleAttribute;
380 using UIntAttribute = HepMC3::UIntAttribute;
381 using ULongAttribute = HepMC3::ULongAttribute;
382 using ULongLongAttribute = HepMC3::ULongLongAttribute;
383 using BoolAttribute = HepMC3::BoolAttribute;
385 if (putAttributeInfoImpl<IntAttribute, int>(eventHeader,
name,
a)) {
388 if (putAttributeInfoImpl<LongAttribute, int>(eventHeader,
name,
a)) {
391 if (putAttributeInfoImpl<FloatAttribute, float>(eventHeader,
name,
a)) {
394 if (putAttributeInfoImpl<DoubleAttribute, float>(eventHeader,
name,
a)) {
397 if (putAttributeInfoImpl<StringAttribute, std::string>(eventHeader,
name,
a)) {
400 if (putAttributeInfoImpl<CharAttribute, char>(eventHeader,
name,
a)) {
403 if (putAttributeInfoImpl<LongLongAttribute, int>(eventHeader,
name,
a)) {
406 if (putAttributeInfoImpl<LongDoubleAttribute, float>(eventHeader,
name,
a)) {
409 if (putAttributeInfoImpl<UIntAttribute, int>(eventHeader,
name,
a)) {
412 if (putAttributeInfoImpl<ULongAttribute, int>(eventHeader,
name,
a)) {
415 if (putAttributeInfoImpl<ULongLongAttribute, int>(eventHeader,
name,
a)) {
418 if (putAttributeInfoImpl<BoolAttribute, bool>(eventHeader,
name,
a)) {
431 eventHeader->
putInfo<std::string>(Key::generator,
"hepmc");
432 eventHeader->
putInfo<
int>(Key::generatorVersion, HEPMC3_VERSION_CODE);
434 auto xSection =
mEvent->cross_section();
435 auto pdfInfo =
mEvent->pdf_info();
436 auto hiInfo =
mEvent->heavy_ion();
444 auto attStr =
mEvent->attribute_as_string(
"GenHeavyIon");
445 if (!attStr.empty() && attStr[0] ==
'v') {
446 std::istringstream is(attStr);
450 auto hi = std::make_shared<HepMC3::GenHeavyIon>();
451 double spectNeutrons, spectProtons, eccentricity, userCentEst;
452 is >> hi->Ncoll_hard >> hi->Npart_proj >> hi->Npart_targ >> hi->Ncoll >> spectNeutrons >> spectProtons
453 >> hi->N_Nwounded_collisions >> hi->Nwounded_N_collisions >> hi->Nwounded_Nwounded_collisions >> hi->impact_parameter >> hi->event_plane_angle >> eccentricity
454 >> hi->sigma_inel_NN >> hi->centrality >> userCentEst
455 >> hi->Nspec_proj_n >> hi->Nspec_targ_n >> hi->Nspec_proj_p >> hi->Nspec_targ_p;
457 LOG(
debug) <<
"GenHeavyIon: using manual v0 parser (workaround for HepMC3 from_string bug)";
460 LOG(warn) <<
"GenHeavyIon: manual v0 parser also failed on: [" << attStr <<
"]";
468 eventHeader->
putInfo<
float>(Key::xSection, xSection->xsec());
469 eventHeader->
putInfo<
float>(Key::xSectionError, xSection->xsec_err());
470 eventHeader->
putInfo<
int>(Key::acceptedEvents,
471 xSection->get_accepted_events());
472 eventHeader->
putInfo<
int>(Key::attemptedEvents,
473 xSection->get_attempted_events());
478 for (
auto w :
mEvent->weights()) {
480 eventHeader->
putInfo<
float>(Key::weight + post,
w);
482 eventHeader->
putInfo<
float>(Key::xSection, xSection->xsec(iw));
483 eventHeader->
putInfo<
float>(Key::xSectionError, xSection->xsec_err(iw));
490 eventHeader->
putInfo<
int>(Key::pdfParton1Id, pdfInfo->parton_id[0]);
491 eventHeader->
putInfo<
int>(Key::pdfParton2Id, pdfInfo->parton_id[1]);
492 eventHeader->
putInfo<
float>(Key::pdfX1, pdfInfo->x[0]);
493 eventHeader->
putInfo<
float>(Key::pdfX2, pdfInfo->x[1]);
494 eventHeader->
putInfo<
float>(Key::pdfScale, pdfInfo->scale);
495 eventHeader->
putInfo<
float>(Key::pdfXF1, pdfInfo->xf[0]);
496 eventHeader->
putInfo<
float>(Key::pdfXF2, pdfInfo->xf[1]);
497 eventHeader->
putInfo<
int>(Key::pdfCode1, pdfInfo->pdf_id[0]);
498 eventHeader->
putInfo<
int>(Key::pdfCode2, pdfInfo->pdf_id[1]);
503 eventHeader->SetB(hiInfo->impact_parameter);
504 eventHeader->
putInfo<
float>(Key::impactParameter,
505 hiInfo->impact_parameter);
506 eventHeader->
putInfo<
int>(Key::nPart,
507 hiInfo->Npart_proj + hiInfo->Npart_targ);
508 eventHeader->
putInfo<
int>(Key::nPartProjectile, hiInfo->Npart_proj);
509 eventHeader->
putInfo<
int>(Key::nPartTarget, hiInfo->Npart_targ);
510 eventHeader->
putInfo<
int>(Key::nColl, hiInfo->Ncoll);
511 eventHeader->
putInfo<
int>(Key::nCollHard, hiInfo->Ncoll_hard);
512 eventHeader->
putInfo<
int>(Key::nCollNNWounded,
513 hiInfo->N_Nwounded_collisions);
514 eventHeader->
putInfo<
int>(Key::nCollNWoundedN,
515 hiInfo->Nwounded_N_collisions);
516 eventHeader->
putInfo<
int>(Key::nCollNWoundedNwounded,
517 hiInfo->Nwounded_Nwounded_collisions);
518 eventHeader->
putInfo<
double>(Key::planeAngle, hiInfo->event_plane_angle);
519 eventHeader->
putInfo<
float>(Key::sigmaInelNN, hiInfo->sigma_inel_NN);
520 eventHeader->
putInfo<
float>(Key::centrality, hiInfo->centrality);
521 eventHeader->
putInfo<
int>(Key::nSpecProjectileProton, hiInfo->Nspec_proj_p);
522 eventHeader->
putInfo<
int>(Key::nSpecProjectileNeutron, hiInfo->Nspec_proj_n);
523 eventHeader->
putInfo<
int>(Key::nSpecTargetProton, hiInfo->Nspec_targ_p);
524 eventHeader->
putInfo<
int>(Key::nSpecTargetNeutron, hiInfo->Nspec_targ_n);
527 for (
auto na :
mEvent->attributes()) {
528 std::string
name = na.first;
529 if (
name ==
"GenPdfInfo" ||
530 name ==
"GenCrossSection" ||
531 name ==
"GenHeavyIon") {
535 for (
auto ia : na.second) {
540 putAttributeInfo(eventHeader,
name + post, at);
550 LOG(
debug) <<
"Reseting the reader";
555 LOG(
debug) <<
"No more files to read, return false";
566 if (not
mCmd.empty()) {
572 LOG(info) <<
"Creating ASCII reader of " <<
filename;
584 LOG(info) <<
"Reader is " <<
mReader.get() <<
" " << ret;
625 if (not
mCmd.empty()) {
645 LOG(
debug) <<
"EG command line is \"" << cmd <<
"\"";
649 LOG(fatal) <<
"Failed to spawn \"" << cmd <<
"\"";
o2::monitoring::tags::Key Key
Utility functions for MC particles.
void updateHeader(o2::dataformats::MCEventHeader *eventHeader) override
void setEventsToSkip(uint64_t val)
Bool_t importParticles() override
~GeneratorHepMC() override
void pruneEvent(Select select)
Bool_t generateEvent() override
HepMC3::GenEvent * mEvent
std::shared_ptr< HepMC3::Reader > mReader
void setup(const GeneratorFileOrCmdParam ¶m0, const GeneratorHepMCParam ¶m, const conf::SimConfig &config)
std::string mInterfaceName
std::vector< TParticle > mParticles
static void encodeParticleStatusAndTracking(TParticle &particle, bool wanttracking=true)
GLuint const GLchar * name
GLboolean GLboolean GLboolean GLboolean a
GLubyte GLubyte GLubyte GLubyte w
std::vector< InputSpec > select(char const *matcher="")
a couple of static helper functions to create timestamp values for CCDB queries or override obsolete ...
std::string to_string(gsl::span< T, Size > span)
virtual bool ensureFiles()
void setFileNames(const std::string &filenames)
void setup(const GeneratorFileOrCmdParam ¶m, const conf::SimConfig &config)
std::list< std::string > mFileNames
static constexpr unsigned int sStopGraceMillis
virtual bool terminateCmd(unsigned int graceMillis=0)
virtual std::string makeCmdLine() const
virtual bool removeTemp() const
virtual bool executeCmdLine(const std::string &cmd)
virtual bool makeTemp(const bool &)
virtual bool makeFifo() const
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"