281 const std::vector<int>& old2New,
283 std::vector<bool>&
done,
286 FirstLastRelative firstLast,
287 const std::string& what,
288 const std::string& ind)
291 auto findNew = [old2New](
size_t old) ->
int {
294 int newIdx = findNew(
index);
295 int hepmc =
event[
index].statusHepMC();
299 << newIdx <<
" (" << hepmc <<
") ";
301 LOG(
debug) << ind <<
" already done";
306 using IdList = std::pair<int, int>;
307 constexpr int invalid = 0xFFFFFFF;
308 IdList newRelatives = std::make_pair(invalid, -invalid);
311 auto addId = [](IdList& l,
size_t id) {
312 l.first = std::min(
int(
id), l.first);
313 l.second = std::max(
int(
id), l.second);
317 auto& particle =
event[
index];
318 auto relatives = getter(particle);
320 LOG(
debug) << ind <<
" Check " << what <<
"s ["
321 << std::setw(3) << firstLast(particle).first <<
","
322 << std::setw(3) << firstLast(particle).second <<
"] "
325 for (
auto relativeIdx : relatives) {
326 int newRelative = findNew(relativeIdx);
327 if (newRelative >= 0) {
332 << relativeIdx <<
" -> "
333 << newRelative <<
" to be kept" << std::endl;
334 addId(newRelatives, newRelative);
339 << relativeIdx <<
" not to be kept "
340 << (
done[relativeIdx] ?
"already done" :
"to be done")
344 auto& relative =
event[relativeIdx];
345 if (not
done[relativeIdx]) {
360 auto grandRelatives = firstLast(relative);
361 int grandRelative1 = grandRelatives.first;
362 int grandRelative2 = grandRelatives.second;
363 assert(grandRelative1 != invalid);
364 assert(grandRelative2 != -invalid);
365 if (grandRelative1 > 0) {
366 addId(newRelatives, grandRelative1);
368 if (grandRelative2 > 0) {
369 addId(newRelatives, grandRelative2);
373 << relativeIdx <<
" gave new relatives "
374 << grandRelative1 <<
" -> " << grandRelative2;
377 << (newRelatives.second - newRelatives.first + 1) <<
" new "
380 if (newRelatives.first != invalid) {
383 int newRelative1 = newRelatives.first;
384 int newRelative2 = newRelatives.second;
385 setter(particle, newRelative1, newRelative2);
386 LOG(
debug) << ind <<
" " << what <<
"s: "
387 << firstLast(particle).first <<
" ("
388 << newRelative1 <<
"),"
389 << firstLast(particle).second <<
" ("
390 << newRelative2 <<
")";
393 setter(particle, 0, 0);
402 std::vector<int> old2new(
event.size(), -1);
409 for (
size_t i = 1;
i <
event.size();
i++) {
410 auto& particle =
event[
i];
417 auto findNew = [old2new](
size_t old) ->
int {
422 auto getMothers = [](
const Pythia8::Particle& particle) {
return particle.motherList(); };
423 auto setMothers = [](Pythia8::Particle& particle,
int m1,
int m2) { particle.mothers(m1, m2); };
424 auto firstLastMothers = [](
const Pythia8::Particle& particle) {
return std::make_pair(particle.mother1(), particle.mother2()); };
426 std::vector<bool> motherDone(
event.size(),
false);
427 for (
size_t i = 1;
i <
event.size(); ++
i) {
439 auto getDaughters = [](
const Pythia8::Particle& particle) {
444 if (std::abs(particle.status()) == 13) {
445 int d1 = particle.daughter1();
446 int d2 = particle.daughter2();
447 if (d1 == 0 and d2 == 0) {
448 return std::vector<int>();
451 return std::vector<int>{d1};
454 std::vector<int> ret(d2-d1+1);
455 std::iota(ret.begin(), ret.end(), d1);
458 return std::vector<int>{d2,d1};
460 return particle.daughterList(); };
461 auto setDaughters = [](Pythia8::Particle& particle,
int d1,
int d2) { particle.daughters(d1, d2); };
462 auto firstLastDaughters = [](
const Pythia8::Particle& particle) {
return std::make_pair(particle.daughter1(), particle.daughter2()); };
464 std::vector<bool> daughterDone(
event.size(),
false);
465 for (
size_t i =
event.size() - 1;
i > 0; --
i) {
477 Pythia8::Event pruned;
478 pruned.init(
"Pruned event", &
mPythia.particleData);
481 for (
size_t i = 1;
i <
event.size();
i++) {
482 int newIdx = findNew(
i);
487 auto particle =
event[
i];
488 int realIdx = pruned.append(particle);
489 assert(realIdx == newIdx);
505 using IdList = std::pair<int, int>;
507 auto addId = [](IdList& l,
size_t id) {
508 l.first = std::min(
int(
id), l.first);
509 l.second = std::max(
int(
id), l.second);
511 constexpr int invalid = 0xFFFFFFF;
513 std::vector<bool> shareDone(pruned.size(),
false);
514 for (
size_t i = 1;
i < pruned.size();
i++) {
519 auto& particle = pruned[
i];
520 auto daughters = particle.daughterList();
521 IdList allDaughters = std::make_pair(invalid, -invalid);
522 IdList allMothers = std::make_pair(invalid, -invalid);
523 addId(allMothers,
i);
524 for (
auto daughterIdx : daughters) {
526 addId(allDaughters, daughterIdx);
527 auto& daughter = pruned[daughterIdx];
528 auto otherMothers = daughter.motherList();
529 for (
auto otherMotherIdx : otherMothers) {
534 addId(allMothers, otherMotherIdx);
537 auto& otherMother = pruned[otherMotherIdx];
538 int otherDaughter1 = otherMother.daughter1();
539 int otherDaughter2 = otherMother.daughter2();
540 if (otherDaughter1 > 0) {
541 addId(allDaughters, otherDaughter1);
543 if (otherDaughter2 > 0) {
544 addId(allDaughters, otherDaughter2);
555 int minDaughter = allDaughters.first;
556 int maxDaughter = allDaughters.second;
557 int minMother = allMothers.first;
558 int maxMother = allMothers.second;
559 if (minMother != invalid) {
561 for (
size_t motherIdx = minMother; motherIdx <= maxMother;
563 shareDone[motherIdx] =
true;
564 if (minDaughter == invalid) {
565 pruned[motherIdx].daughters(0, 0);
567 pruned[motherIdx].daughters(minDaughter, maxDaughter);
571 if (minDaughter != invalid) {
574 for (
size_t daughterIdx = minDaughter; daughterIdx <= maxDaughter;
576 if (minMother == invalid) {
577 pruned[daughterIdx].mothers(0, 0);
579 pruned[daughterIdx].mothers(minMother, maxMother);
585 LOG(info) <<
"Pythia event was pruned from " <<
event.size()
586 <<
" to " << pruned.size() <<
" particles";
625 std::function<bool(
const Pythia8::Particle&)> partonSelect = [](
const Pythia8::Particle&) {
return true; };
627 if (not includeParton) {
630 partonSelect = [](
const Pythia8::Particle& particle) {
631 switch (particle.statusHepMC()) {
645 auto finalSelect = [partonSelect,
this](
const Pythia8::Particle& p) {
return partonSelect(p) &&
mUserFilterFcn(p); };
650 auto nParticles =
event.size();
651 for (Int_t iparticle = 1; iparticle < nParticles; iparticle++) {
653 auto particle =
event[iparticle];
654 auto pdg = particle.id();
660 particle.mother1() - 1,
661 particle.mother2() - 1,
662 particle.daughter1() - 1,
663 particle.daughter2() - 1,
673 particle.statusHepMC() == 1);
687 eventHeader->
putInfo<std::string>(Key::generator,
"pythia8");
688 eventHeader->
putInfo<
int>(Key::generatorVersion, PYTHIA_VERSION_INTEGER);
689 eventHeader->
putInfo<std::string>(Key::processName,
mPythia.info.name());
695 eventHeader->
putInfo<
int>(Key::acceptedEvents, info.nAccepted());
696 eventHeader->
putInfo<
int>(Key::attemptedEvents, info.nTried());
699 eventHeader->
putInfo<
int>(Key::pdfParton1Id, info.id1pdf());
700 eventHeader->
putInfo<
int>(Key::pdfParton2Id, info.id2pdf());
701 eventHeader->
putInfo<
float>(Key::pdfX1, info.x1pdf());
702 eventHeader->
putInfo<
float>(Key::pdfX2, info.x2pdf());
703 eventHeader->
putInfo<
float>(Key::pdfScale, info.QFac());
704 eventHeader->
putInfo<
float>(Key::pdfXF1, info.pdf1());
705 eventHeader->
putInfo<
float>(Key::pdfXF2, info.pdf2());
708 eventHeader->
putInfo<
float>(Key::xSection, info.sigmaGen() * 1e9);
709 eventHeader->
putInfo<
float>(Key::xSectionError, info.sigmaErr() * 1e9);
712 eventHeader->
putInfo<
float>(Key::eventScale, info.QRen());
713 eventHeader->
putInfo<
int>(Key::mpi, info.nMPI());
717 auto xsecErr = info.weightContainerPtr->getTotalXsecErr();
718 for (
auto w : info.weightContainerPtr->getTotalXsec()) {
720 eventHeader->
putInfo<
float>(Key::weight + post, info.weightValueByIndex(iw));
721 eventHeader->
putInfo<
float>(Key::xSection + post,
w * 1e9);
722 eventHeader->
putInfo<
float>(Key::xSectionError + post, xsecErr[iw] * 1e9);
726#if PYTHIA_VERSION_INTEGER < 8300
727 auto hiinfo =
mPythia.info.hiinfo;
729 auto hiinfo =
mPythia.info.hiInfo;
734 eventHeader->SetB(hiinfo->b());
735 eventHeader->
putInfo<
double>(Key::impactParameter, hiinfo->b());
737#if PYTHIA_VERSION_INTEGER >= 8310
738 eventHeader->
putInfo<
double>(Key::planeAngle, hiinfo->phi());
740 auto bImp = hiinfo->b();
743 int nPartProtonProj, nPartNeutronProj, nPartProtonTarg, nPartNeutronTarg;
744 int nRemnProtonProj, nRemnNeutronProj, nRemnProtonTarg, nRemnNeutronTarg;
745 int nFreeNeutronProj, nFreeProtonProj, nFreeNeutronTarg, nFreeProtonTarg;
748 getNpart(nPartProtonProj, nPartNeutronProj, nPartProtonTarg, nPartNeutronTarg);
749 getNremn(nRemnProtonProj, nRemnNeutronProj, nRemnProtonTarg, nRemnNeutronTarg);
750 getNfreeSpec(nFreeNeutronProj, nFreeProtonProj, nFreeNeutronTarg, nFreeProtonTarg);
751 eventHeader->
putInfo<
int>(Key::nColl, nColl);
753 eventHeader->
putInfo<
int>(
"Npart", nPart);
754 eventHeader->
putInfo<
int>(
"Npart_proj_p", nPartProtonProj);
755 eventHeader->
putInfo<
int>(
"Npart_proj_n", nPartNeutronProj);
756 eventHeader->
putInfo<
int>(
"Npart_targ_p", nPartProtonTarg);
757 eventHeader->
putInfo<
int>(
"Npart_targ_n", nPartNeutronTarg);
758 eventHeader->
putInfo<
int>(
"Nremn_proj_p", nRemnProtonProj);
759 eventHeader->
putInfo<
int>(
"Nremn_proj_n", nRemnNeutronProj);
760 eventHeader->
putInfo<
int>(
"Nremn_targ_p", nRemnProtonTarg);
761 eventHeader->
putInfo<
int>(
"Nremn_targ_n", nRemnNeutronTarg);
762 eventHeader->
putInfo<
int>(
"Nfree_proj_n", nFreeNeutronProj);
763 eventHeader->
putInfo<
int>(
"Nfree_proj_p", nFreeProtonProj);
764 eventHeader->
putInfo<
int>(
"Nfree_targ_n", nFreeNeutronTarg);
765 eventHeader->
putInfo<
int>(
"Nfree_targ_p", nFreeProtonTarg);
773 eventHeader->
putInfo<
int>(Key::nPartProjectile,
774 hiinfo->nAbsProj() + hiinfo->nDiffProj());
775 eventHeader->
putInfo<
int>(Key::nPartTarget,
776 hiinfo->nAbsTarg() + hiinfo->nDiffTarg());
777 eventHeader->
putInfo<
int>(Key::nCollHard, hiinfo->nCollNDTot());
875#if PYTHIA_VERSION_INTEGER < 8300
876 auto hiinfo = info.hiinfo;
878 auto hiinfo = info.hiInfo;
886 nPart = (hiinfo->nAbsProj() + hiinfo->nDiffProj() +
887 hiinfo->nAbsTarg() + hiinfo->nDiffTarg());
888 if (not hiinfo->subCollisionsPtr()) {
892 int nProtonProj, nNeutronProj, nProtonTarg, nNeutronTarg;
893 getNpart(info, nProtonProj, nNeutronProj, nProtonTarg, nNeutronTarg);
894 nPart = nProtonProj + nNeutronProj + nProtonTarg + nNeutronTarg;
904#if PYTHIA_VERSION_INTEGER < 8300
905 auto hiinfo = info.hiinfo;
907 auto hiinfo = info.hiInfo;
910 nProtonProj = nNeutronProj = nProtonTarg = nNeutronTarg = 0;
915 nProtonProj = hiinfo->nAbsProj() + hiinfo->nDiffProj();
916 nProtonTarg = hiinfo->nAbsTarg() + hiinfo->nDiffTarg();
917 if (not hiinfo->subCollisionsPtr()) {
918#if PYTHIA_VERSION_INTEGER < 8310
919 LOG(fatal) <<
"No sub-collision pointer from Pythia";
925 std::vector<Pythia8::Nucleon*> projW;
926 std::vector<Pythia8::Nucleon*> targW;
929 auto scptr = hiinfo->subCollisionsPtr();
930 for (
auto sc : *scptr) {
933 auto pW = sc.proj->status() == Pythia8::Nucleon::ABS || sc.proj->status() == Pythia8::Nucleon::DIFF;
934 auto tW = sc.targ->status() == Pythia8::Nucleon::ABS || sc.targ->status() == Pythia8::Nucleon::DIFF;
937 if (pW && std::find(projW.begin(), projW.end(), sc.proj) == projW.end()) {
938 projW.push_back(sc.proj);
939 if (sc.proj->id() == 2212) {
941 }
else if (sc.proj->id() == 2112) {
947 if (tW && std::find(targW.begin(), targW.end(), sc.targ) == targW.end()) {
948 targW.push_back(sc.targ);
949 if (sc.targ->id() == 2212) {
951 }
else if (sc.targ->id() == 2112) {