19#include "HepMC3/ReaderFactory.h"
20#include "HepMC3/ReaderAscii.h"
21#include "HepMC3/ReaderAsciiHepMC2.h"
22#include "HepMC3/GenEvent.h"
23#include "HepMC3/GenParticle.h"
24#include "HepMC3/GenVertex.h"
25#include "HepMC3/FourVector.h"
26#include "HepMC3/Version.h"
30#include <fairlogger/Logger.h>
31#include "FairPrimaryGenerator.h"
58 mEvent =
new HepMC3::GenEvent();
68 LOG(info) <<
"Destructing GeneratorHepMC";
120 if (not
param.fileName.empty()) {
121 LOG(warn) <<
"The use of the key \"HepMC.fileName\" is "
122 <<
"deprecated, use \"GeneratorFileOrCmd.fileNames\" instead";
142 if (
param.version != 0 and
mCmd.empty()) {
143 LOG(warn) <<
"The key \"HepMC.version\" is no longer needed when "
144 <<
"reading from files. The format version of the input files "
145 <<
"are automatically deduced. However, it is mandatory when reading "
146 <<
"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);
546 eventHeader->
putInfo<std::string>(
"forwarding-generator",
"generatorHepMC");
557 LOG(
debug) <<
"Reseting the reader";
562 LOG(
debug) <<
"No more files to read, return false";
573 if (not
mCmd.empty()) {
579 LOG(info) <<
"Creating ASCII reader of " <<
filename;
591 LOG(info) <<
"Reader is " <<
mReader.get() <<
" " << ret;
607 if (info.m_error or info.m_remote or info.m_pipe or
608 not(info.m_asciiv3 or info.m_iogenevent)) {
615 LOG(error) <<
"Could not open " <<
filename <<
" to index its events";
618 std::shared_ptr<HepMC3::Reader> reader;
620 reader = std::make_shared<HepMC3::ReaderAsciiHepMC2>(
stream);
622 reader = std::make_shared<HepMC3::ReaderAscii>(
stream);
624 if (not reader or reader->failed()) {
625 LOG(error) <<
"Could not open " <<
filename <<
" to index its events";
630 constexpr int max_events = 100000000;
631 HepMC3::GenEvent
event;
633 auto here = (std::streamoff)
stream->tellg();
635 reader->read_event(
event);
636 if (reader->failed()) {
642 LOG(warn) <<
"Stopped indexing the events of " <<
filename <<
" at " << max_events;
645 LOG(error) <<
"No event found in HepMC file " <<
filename;
678 mEvent->set_units(HepMC3::Units::GEV, HepMC3::Units::MM);
696 auto j = (
int)gRandom->Integer(
i + 1);
712 << (requested > 0 ?
" (" +
std::to_string(requested) +
" were requested)" :
"")
713 <<
". Provide more events or allow reusing them via roundRobin";
717 LOG(info) <<
"GeneratorHepMC - Reached the end of the input; reusing its events";
730 LOG(info) <<
"GeneratorHepMC - Picking event " <<
entry;
777 if (not
mCmd.empty()) {
797 LOG(
debug) <<
"EG command line is \"" << cmd <<
"\"";
801 LOG(fatal) <<
"Failed to spawn \"" << cmd <<
"\"";
831 if (not
mCmd.empty()) {
832 LOG(fatal) <<
"HepMC.randomize/HepMC.roundRobin cannot be used when the events "
833 <<
"come from a command, as the pipe can only be read once";
837 LOG(fatal) <<
"HepMC.randomize/HepMC.roundRobin need exactly one input file, but "
845 LOG(info) <<
"GeneratorHepMC: the event order is drawn with gRandom (" << gRandom->ClassName()
846 <<
") seeded with " << gRandom->GetSeed();
852 LOG(fatal) <<
"HepMC.randomize/HepMC.roundRobin need an input the events can be "
853 <<
"picked from in any order, which means a plain HepMC3 or HepMC2 "
854 <<
"ASCII file; " <<
filename <<
" is not one. Convert it, or convert "
855 <<
"it to O2 kinematics and read it back with -g extkinO2, which "
856 <<
"randomizes over a TTree";
861 LOG(fatal) <<
"HepMC.eventsToSkip (" <<
mEventsToSkip <<
") leaves no event of the "
868 LOG(warn) <<
"This job will request " << requested <<
" events, but the input holds "
869 <<
"only " <<
mEventOrder.size() <<
" usable event(s). The job will stop "
870 <<
"with 'ran out of events' - provide more events or enable roundRobin";
873 <<
" events, " << (
mRandomize ?
"randomized" :
"sequential") <<
" order)";
o2::monitoring::tags::Key Key
Utility functions for MC particles.
void updateHeader(o2::dataformats::MCEventHeader *eventHeader) override
void setEventsToSkip(uint64_t val)
std::vector< int > mEventOrder
bool readEntry(int entry)
std::vector< std::streamoff > mEventOffsets
Bool_t importParticles() override
void setupHepMC(const HepMCGenConfig ¶m)
~GeneratorHepMC() override
Bool_t generateEventOrdered()
void establishEventOrder()
void pruneEvent(Select select)
Bool_t generateEvent() override
std::shared_ptr< std::istream > mIndexedStream
HepMC3::GenEvent * mEvent
void setup(const GeneratorFileOrCmdParam ¶m0, const HepMCGenConfig ¶m, const conf::SimConfig &config)
std::shared_ptr< HepMC3::Reader > mReader
bool buildIndex(const std::string &filename)
std::string mCurrentFileName
std::string mInterfaceName
static unsigned int getTotalNEvents()
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"