diff --git a/MC/config/PWGHF/external/generator/generator_pythia8_embed_charmnuclei.C b/MC/config/PWGHF/external/generator/generator_pythia8_embed_charmnuclei.C new file mode 100644 index 000000000..4b6e9a3f7 --- /dev/null +++ b/MC/config/PWGHF/external/generator/generator_pythia8_embed_charmnuclei.C @@ -0,0 +1,305 @@ +#include "FairGenerator.h" +#include "Generators/GeneratorPythia8.h" +#include "Pythia8/Pythia.h" +#include "TRandom.h" +#include "TF1.h" +#include "TMath.h" +#include +#include +#include +#include + +R__ADD_INCLUDE_PATH($O2DPG_MC_CONFIG_ROOT) +#include "MC/config/common/external/generator/CoalescencePythia8.h" + +using namespace Pythia8; + +class GeneratorPythia8HFEmbedCharmNuclei : public o2::eventgen::GeneratorPythia8 +{ + public: + + /// constructor + GeneratorPythia8HFEmbedCharmNuclei(int pdgCode = 2010010020, float lifetime = 1.f, int nCharmNucleiPerEvent = 10, float yMin = -1.f, float yMax = 1.f, float ptMax = 25.f, bool trivialCoal = false, float coalMomentum = 0.2, float fracFromB = 0.f) + { + nNumberOfCharmNucleiPerEvent = nCharmNucleiPerEvent; + mRapidityMinCharmNuclei = yMin; + mRapidityMaxCharmNuclei = yMax; + mPtMaxCharmNuclei = ptMax; + mTrivialCoal = trivialCoal; + mCoalMomentum = coalMomentum; + mFractionFromBeauty = fracFromB; + mPdgCharmNucleus = pdgCode; + mSign = 1; + if (std::abs(mPdgCharmNucleus) == 2010010020) { + mMassCharmNucleus = 3.226f; + } else { + LOG(fatal) << "********** [GeneratorPythia8HFEmbedCharmNuclei] Only c-deuteron (pdg=2010010020) currently supported! Exit **********"; + } + mLifetimeCharmNucleus = lifetime; + mDecayDistr = new TF1("mDecayDistr", "TMath::Exp(-x * 1./[0])", 0., mLifetimeCharmNucleus * 100); + mDecayDistr->SetNpx(10000); + mDecayDistr->SetParameter(0, mLifetimeCharmNucleus); + mDecayDistrLb = new TF1("mDecayDistrLb", "TMath::Exp(-x * 1./[0])", 0., 44.f); + mDecayDistrLb->SetParameter(0, 0.440f); // lifetime of Lambda_b in mm/c + mDecayDistrLb->SetNpx(10000); + mPtDistrLb = new TF1("mPtDistrLb","[0]*x/TMath::Power((1+TMath::Power(x/[1],[3])),[2])",0.,100.); + mPtDistrLb->SetParameters(1000., 6.97355, 3.20721, 1.71678); + mPtDistrLb->SetNpx(10000); + + Print(); + + auto& param = o2::eventgen::GeneratorPythia8Param::Instance(); + LOG(info) << "Init \'GeneratorPythia8HFEmbedCharmNuclei\' with following parameters"; + LOG(info) << param; + if (param.config.empty()) { + LOG(fatal) << "Failed to init \'GeneratorPythia8\': problems with configuration file "; + } + std::string cfg = gSystem->ExpandPathName(param.config.c_str()); + LOG(info) << "GeneratorPythia8HFEmbedCharmNuclei Reading configuration from file: " << cfg; + if (!mPythiaGun.readFile(cfg, true)) { + LOG(fatal) << "Failed to init \'GeneratorPythia8\': problems with configuration file " << cfg; + } + + if (!mPythiaGun.init()) { + LOG(fatal) << "Failed to init \'GeneratorPythia8\': init returned with error"; + } + } + + /// Destructor + ~GeneratorPythia8HFEmbedCharmNuclei() = default; + + /// Print the input + void Print() + { + LOG(info) << "********** GeneratorPythia8HFEmbedCharmNuclei configuration dump **********"; + LOG(info) << Form("* PDG code of charm nuclei to be injected: %d", mPdgCharmNucleus); + LOG(info) << Form("* Mass of charm nuclei to be injected (GeV/c2): %f", mMassCharmNucleus); + LOG(info) << Form("* Lifetime of charm nuclei to be injected (mm): %f", mLifetimeCharmNucleus); + LOG(info) << Form("* Number of charm nuclei injected per event: %d", nNumberOfCharmNucleiPerEvent); + LOG(info) << Form("* Charmed nucleus rapidity: %f - %f", mRapidityMinCharmNuclei, mRapidityMaxCharmNuclei); + LOG(info) << Form("* Charmed nucleus pT max (prompt): %f", mPtMaxCharmNuclei); + LOG(info) << Form("* Trivial coalescence: %d", mTrivialCoal); + LOG(info) << Form("* Coalescence momentum: %f", mCoalMomentum); + LOG(info) << Form("* Fraction from beauty: %f", mFractionFromBeauty); + LOG(info) << "***********************************************************************"; + } + + void setHadronRapidity(float yMin, float yMax) + { + mRapidityMinCharmNuclei = yMin; + mRapidityMaxCharmNuclei = yMax; + }; + + void setUsedSeed(unsigned int seed) + { + mUsedSeed = seed; + }; + + unsigned int getUsedSeed() const + { + return mUsedSeed; + }; + + //__________________________________________________________________ + bool generateEvent() override + { + // we start from an empty event + mPythia.event.reset(); + + // we simulate c-deuteron decays + for (int iCharmNuclei{0}; iCharmNuclei 0) ? mSign = -1 : mSign = 1; + if (nNumberOfCharmNucleiPerEvent % 2 != 0 && iCharmNuclei == nNumberOfCharmNucleiPerEvent - 1) { + if (gRandom->Rndm() < 0.5) { + mSign = 1; + } + } + + int pdgToGen = mPdgCharmNucleus; + float massToGen = mMassCharmNucleus; + float lifetimeToGen = 0.f; + float minRapToGen = mRapidityMinCharmNuclei; + float maxRapToGen = mRapidityMaxCharmNuclei; + bool isFromB = gRandom->Rndm() < mFractionFromBeauty; + // we determine if it's prompt or non-prompt + if (isFromB) { + pdgToGen = 5122; // we generate a Lambda_b and we let it decay into the charmed nucleus, no other beauty hadrons are considered + massToGen = 5.61940f; // mass of Lambda_b (GeV/c2) + lifetimeToGen = mDecayDistrLb->GetRandom(); + minRapToGen *= 2; + maxRapToGen *= 2; + } else { + lifetimeToGen = mDecayDistr->GetRandom(); + } + + auto pt = (!isFromB) ? gRandom->Uniform(0., mPtMaxCharmNuclei) : mPtDistrLb->GetRandom(); + auto y = gRandom->Uniform(minRapToGen, maxRapToGen); + auto phi = gRandom->Uniform(0, TMath::TwoPi()); + auto px = pt * TMath::Cos(phi); + auto py = pt * TMath::Sin(phi); + auto mt = TMath::Sqrt(massToGen * massToGen + pt * pt); + auto pz = mt * TMath::SinH(y); + auto p = TMath::Sqrt(pt * pt + pz * pz); + auto e = TMath::Sqrt(massToGen * massToGen + p * p); + + Particle particle; + particle.id(mSign * pdgToGen); + particle.status(83); + particle.m(massToGen); + particle.px(px); + particle.py(py); + particle.pz(pz); + particle.e(e); + particle.xProd(0.f); + particle.yProd(0.f); + particle.zProd(0.f); + particle.tau(lifetimeToGen); + mPythiaGun.particleData.mayDecay(5122, true); // force decay + mPythiaGun.particleData.mayDecay(mPdgCharmNucleus, true); // force decay + + bool isCoalSuccess{false}; + int nTrials{0}; + while(!isCoalSuccess || nTrials > 1e4) { + mPythiaGun.event.reset(); + mPythiaGun.event.append(particle); + mPythiaGun.moreDecays(); + std::array dausToCoal = {-1, -1}; + std::vector pdgShortLivedResos = {313, 2224, 102134}; + bool isResoFound{false}; + int idxCharmNucleus{-1}; + for (int iPart{0}; iPart= idxCharmNucleus) { + // we need to change the indices of the daughter particles to point to the charmed nucleus + auto dauList = part.daughterList(); + for (auto const& dau : dauList) { + mPythiaGun.event[dau].mother1(idxCharmNucleus); + } + mPythiaGun.event.remove(iPart, iPart, true); + isResoFound=true; + } + } + if (isResoFound) { // we have to reset all the particles as daughters of the charm nucleus + std::vector idxDausCharmNucleus{}; + for (int iPart{0}; iPart newPartList{}; + std::vector idxToRemove{}; + for (int iPart{idxDausCharmNucleus[0]}; iPart updatedMothers{}; + for (int iPart{0}; iPart{1000010020}, mTrivialCoal, mCoalMomentum, dausToCoal[0], dausToCoal[1], 10.); + if (isCoalSuccess) { + int offset = mPythia.event.size(); // we need to rescale the indices of mothers and daughters, accounting for the particles that are already appended to the event + for (int iPart{0}; iPart 0) { + part.mother1(mother1 + offset - 1); + } + if (mother2 > 0) { + part.mother2(mother2 + offset - 1); + } + if (daughter1 > 0) { + part.daughter1(daughter1 + offset - 1); + } + if (daughter2 > 0) { + part.daughter2(daughter2 + offset - 1); + } + mPythia.event.append(part); + } + } + nTrials++; + } + } + + return true; + } + + +private: + // Properties of selection + float mMassCharmNucleus; /// mass of the charmed nucleus + int mPdgCharmNucleus; /// pdg code of the charmed nucleus + float mLifetimeCharmNucleus; /// lifetime of the charmed nucleus + int nNumberOfCharmNucleiPerEvent; /// number of charmed nuclei injected per event + float mRapidityMinCharmNuclei; /// rapidity min of the generated charmed nuclei + float mRapidityMaxCharmNuclei; /// rapidity max of the generated charmed nuclei + float mPtMaxCharmNuclei; /// pT max of the generated charmed nuclei + unsigned int mUsedSeed; /// seed + bool mTrivialCoal; /// if true, the coalescence is done without checking the distance in the phase space of the nucleons + float mCoalMomentum; /// coalescence momentum + Pythia8::Pythia mPythiaGun; /// Gun generator with decay support + TF1* mDecayDistr; /// Lifetime distribution + TF1* mDecayDistrLb; /// Lifetime distribution for Lb + TF1* mPtDistrLb; /// pt distribution for Lb (power-law fit to FONLL) + float mFractionFromBeauty; /// fraction of charmed nuclei coming from beauty hadrons + int mSign; /// sign of the charmed nuclei to be generated, if 0 they are generated with 50% of probability as particle or antiparticle +}; + + +///___________________________________________________________ +FairGenerator *GenerateHFEmbedCDeuteron(float lifetime = 1.f, int nCharmNucleiPerEvent = 10, float yMin = -1.f, float yMax = 1.f, float ptMax = 25.f, bool trivialCoal = false, float coalMomentum = 0.2f, float fracFromB = 0.25f) +{ + auto myGen = new GeneratorPythia8HFEmbedCharmNuclei(2010010020, lifetime, nCharmNucleiPerEvent, yMin, yMax, ptMax, trivialCoal, coalMomentum, fracFromB); + auto seed = (gRandom->TRandom::GetSeed() % 900000000); + myGen->readString("Random:setSeed on"); + myGen->readString("Random:seed " + std::to_string(seed)); + return myGen; +} diff --git a/MC/config/PWGHF/ini/GeneratorHF_CDeuteron_Injected.ini b/MC/config/PWGHF/ini/GeneratorHF_CDeuteron_Injected.ini new file mode 100644 index 000000000..2a574f340 --- /dev/null +++ b/MC/config/PWGHF/ini/GeneratorHF_CDeuteron_Injected.ini @@ -0,0 +1,10 @@ +#NEV_TEST> 100 +### The external generator derives from GeneratorPythia8. +[GeneratorExternal] +fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/external/generator/generator_pythia8_embed_charmnuclei.C +funcName=GenerateHFEmbedCDeuteron(0.5, 10, -1., 1., 25., 0, 0.4, 0.25) + +### includePartonEvent is needed to keep the c-deuteron in the event record, even if there are no partons in the event +[GeneratorPythia8] +config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/pythia8/generator/pythia8_cdeuteron_to_dkpi.cfg +includePartonEvent=true diff --git a/MC/config/PWGHF/ini/tests/GeneratorHF_CDeuteron_Injected.C b/MC/config/PWGHF/ini/tests/GeneratorHF_CDeuteron_Injected.C new file mode 100644 index 000000000..56d22c72a --- /dev/null +++ b/MC/config/PWGHF/ini/tests/GeneratorHF_CDeuteron_Injected.C @@ -0,0 +1,127 @@ +int External() { + std::string path{"o2sim_Kine.root"}; + + int pdgCDeuteron{2010010020}; + int checkNumberOfCDeuteronPerEvent{10}; + float checkLifetimeCDeuteron{0.05f}; + std::map>> checkDecays{ + {2010010020, {{-321, 211, 1000010020}}} // c-deuteron -> K- + pi+ + deuteron + }; + float checkFracCDeuteronFromBeauty{0.25}; + + TFile file(path.c_str(), "READ"); + if (file.IsZombie()) { + std::cerr << "Cannot open ROOT file " << path << "\n"; + return 1; + } + + auto tree = (TTree *)file.Get("o2sim"); + std::vector *tracks{}; + tree->SetBranchAddress("MCTrack", &tracks); + + int nCDeuteron{}, nCDeuteronGoodDecay{}, nCDeuteronFromBeauty{}; + std::array averageLifetimeCDeuteron{0.f, 0.f}; // prompt and non-prompt + float massCDeuteron = 3.226f; + auto nEvents = tree->GetEntries(); + + for (int i = 0; i < nEvents; i++) { + tree->GetEntry(i); + + for (auto &track : *tracks) { + auto pdg = track.GetPdgCode(); + auto absPdg = std::abs(pdg); + // std::cout << "Event " << i << ": found particle with PDG " << pdg << std::endl; + + if (absPdg == pdgCDeuteron) { // found signal + nCDeuteron++; // count signal PDG + + // std::cout << "Event " << i << ": found c-deuteron with PDG " << pdg << std::endl; + + std::vector pdgsDecay{}; + std::vector pdgsDecayAntiPart{}; + if (track.getFirstDaughterTrackId() >= 0 && track.getLastDaughterTrackId() >= 0) { + for (int j{track.getFirstDaughterTrackId()}; j <= track.getLastDaughterTrackId(); ++j) { + // std::cout << "Fetching daughter track with ID " << j << std::endl; + auto pdgDau = tracks->at(j).GetPdgCode(); + // std::cout << "PDG of daughter track " << j << ": " << pdgDau << std::endl; + pdgsDecay.push_back(pdgDau); + if (pdgDau != 333 && pdgDau != 111) { // phi and pi0 are antiparticles of themselves + pdgsDecayAntiPart.push_back(-pdgDau); + } else { + pdgsDecayAntiPart.push_back(pdgDau); + } + } + } + // std::cout << "Daughters fetched" << std::endl; + + auto mother = track.getMotherTrackId(); + bool isFromBeauty{false}; + if (mother >= 0 && std::abs(tracks->at(mother).GetPdgCode()) == 5122) { // check if c-deuteron comes from Lb + nCDeuteronFromBeauty++; + isFromBeauty = true; + } + + auto dauTrack = tracks->at(track.getFirstDaughterTrackId()); + float decayLength = std::sqrt((track.GetStartVertexCoordinatesX() - dauTrack.GetStartVertexCoordinatesX()) * (track.GetStartVertexCoordinatesX() - dauTrack.GetStartVertexCoordinatesX()) + (track.GetStartVertexCoordinatesY() - dauTrack.GetStartVertexCoordinatesY()) * (track.GetStartVertexCoordinatesY() - dauTrack.GetStartVertexCoordinatesY()) + (track.GetStartVertexCoordinatesZ() - dauTrack.GetStartVertexCoordinatesZ()) * (track.GetStartVertexCoordinatesZ() - dauTrack.GetStartVertexCoordinatesZ())); + if (!isFromBeauty) { + averageLifetimeCDeuteron[0] += decayLength * massCDeuteron / track.GetP(); + } else { + averageLifetimeCDeuteron[1] += decayLength * massCDeuteron / track.GetP(); + } + + std::sort(pdgsDecay.begin(), pdgsDecay.end()); + std::sort(pdgsDecayAntiPart.begin(), pdgsDecayAntiPart.end()); + + for (auto &decay : checkDecays[std::abs(pdg)]) { + if (pdgsDecay == decay || pdgsDecayAntiPart == decay) { + nCDeuteronGoodDecay++; + break; + } + } + // std::cout << "Daughters checked " << std::endl; + } + } + } + + averageLifetimeCDeuteron[0] /= nCDeuteron - nCDeuteronFromBeauty; + averageLifetimeCDeuteron[1] /= nCDeuteronFromBeauty; + + std::cout << "--------------------------------\n"; + std::cout << "# Events: " << nEvents << "\n"; + std::cout <<"# signal c-deuteron: " << nCDeuteron << "\n"; + std::cout <<"# signal c-deuteron decaying in the correct channel: " << nCDeuteronGoodDecay << "\n"; + std::cout <<"# signal c-deuteron from beauty: " << nCDeuteronFromBeauty << "\n"; + std::cout <<"Average lifetime of c-deuteron (prompt): " << averageLifetimeCDeuteron[0] << " (cm) \n"; + std::cout <<"Average lifetime of c-deuteron (non-prompt): " << averageLifetimeCDeuteron[1] << " (cm) \n"; + + float numberOfCDeuteronPerEvent = float(nCDeuteron) / nEvents; + float fracCDeuteronGoodDecay = float(nCDeuteronGoodDecay) / nCDeuteron; + float fracCDeuteronFromBeauty = float(nCDeuteronFromBeauty) / nCDeuteron; + + if (std::abs(numberOfCDeuteronPerEvent - checkNumberOfCDeuteronPerEvent) / numberOfCDeuteronPerEvent > 0.05) { // we put some tolerance since the number of generated events is small + std::cerr << "Number of C-deuterons per event " << numberOfCDeuteronPerEvent << " different than expected " << checkNumberOfCDeuteronPerEvent << "\n"; + return 1; + } + + if (fracCDeuteronGoodDecay < 0.95) { // we put some tolerance since the number of generated events is small + std::cerr << "Fraction of signals decaying into the correct channel " << fracCDeuteronGoodDecay << " lower than expected\n"; + return 1; + } + + if (std::abs(fracCDeuteronFromBeauty - checkFracCDeuteronFromBeauty) / checkFracCDeuteronFromBeauty > 0.10) { // we put some tolerance since the number of generated events is small + std::cerr << "Fraction of signals from beauty " << fracCDeuteronFromBeauty << " different than expected " << checkFracCDeuteronFromBeauty << "\n"; + return 1; + } + + if (std::abs(averageLifetimeCDeuteron[0] - checkLifetimeCDeuteron) / checkLifetimeCDeuteron > 0.10) { // we put some tolerance since the number of generated events is small + std::cerr << "Lifetime for prompt c-deuteron " << averageLifetimeCDeuteron[0] << " different than expected " << checkLifetimeCDeuteron << "\n"; + return 1; + } + + if (std::abs(averageLifetimeCDeuteron[1] - checkLifetimeCDeuteron) / checkLifetimeCDeuteron > 0.10) { // we put some tolerance since the number of generated events is small + std::cerr << "Lifetime for non-prompt c-deuteron " << averageLifetimeCDeuteron[1] << " different than expected " << checkLifetimeCDeuteron << "\n"; + return 1; + } + + return 0; +} diff --git a/MC/config/PWGHF/pythia8/generator/pythia8_cdeuteron_to_dkpi.cfg b/MC/config/PWGHF/pythia8/generator/pythia8_cdeuteron_to_dkpi.cfg new file mode 100644 index 000000000..788e56fe3 --- /dev/null +++ b/MC/config/PWGHF/pythia8/generator/pythia8_cdeuteron_to_dkpi.cfg @@ -0,0 +1,102 @@ +### author: Fabrizio Grosa (fabrizio.grosa@cern.ch) +### since: May 2026 + +### beams (not relevant) +Beams:idA 2212 # proton +Beams:idB 2212 # proton +Beams:eCM 13600. # GeV + +### processes +SoftQCD:inelastic on # all inelastic processes + +### decays +ParticleDecays:limitTau0 on +ParticleDecays:tau0Max 10. + +### add the c-deuteron +### id:all = name antiName spinType chargeType colType m0 mWidth mMin mMax tau0 +2010010020:all = CDeuteron AntiCDeuteron 1 3 0 3.226 0 3.226 3.226 0.5 +2010010020:mayDecay = on + +# same as Λc+ -> p K- π+ including resonances + a neutron +2010010020:oneChannel = 1 0.14400 0 2112 2212 -321 211 ### cd+ -> n p K- π+ (non-resonant) 3.5% +2010010020:addChannel = 1 0.08100 100 2112 2212 -313 ### cd+ -> n p K*0(892) 1.96% +2010010020:addChannel = 1 0.04500 100 2112 2224 -321 ### cd+ -> n Delta++ K- 1.08% +2010010020:addChannel = 1 0.09000 100 2112 102134 211 ### cd+ -> n Lambda(1520) K- 2.20e-3 + +### K*0(892) -> K- π+ +313:onMode = off +313:onIfAll = 321 211 +### for Λc -> Delta++ K- +2224:onMode = off +2224:onIfAll = 2212 211 +### for Λc -> Lambda(1520) K- +102134:onMode = off +102134:onIfAll = 2212 321 + +# Λb0 -> cd+ decays taken from PYTHIA +# NB: cd+ must always be the last daughter, not to screw up replacements in the generator +# 15% 2 body +5122:oneChannel = 1 0.15 0 2010010020 -2212 ### Λb0 -> cd+ anti-p +# 27% 3 body +5122:addChannel = 1 0.054 100 -2212 111 2010010020 ### Λb0 -> cd+ anti-p pi0 +5122:addChannel = 1 0.027 100 -2212 113 2010010020 ### Λb0 -> cd+ anti-p rho0 +5122:addChannel = 1 0.027 100 -2212 221 2010010020 ### Λb0 -> cd+ anti-p eta +5122:addChannel = 1 0.027 100 -2212 223 2010010020 ### Λb0 -> cd+ anti-p omega +5122:addChannel = 1 0.060 100 -2112 -211 2010010020 ### Λb0 -> cd+ anti-n0 pi- +5122:addChannel = 1 0.030 100 -2112 -213 2010010020 ### Λb0 -> cd+ anti-n0 rho- +5122:addChannel = 1 0.010 100 -2214 111 2010010020 ### Λb0 -> cd+ DeltaBar- pi0 +5122:addChannel = 1 0.005 100 -2214 113 2010010020 ### Λb0 -> cd+ DeltaBar- rho0 +5122:addChannel = 1 0.005 100 -2214 221 2010010020 ### Λb0 -> cd+ DeltaBar- eta +5122:addChannel = 1 0.005 100 -2214 223 2010010020 ### Λb0 -> cd+ DeltaBar- omega +5122:addChannel = 1 0.007 100 -2114 -211 2010010020 ### Λb0 -> cd+ DeltaBar0 pi- +5122:addChannel = 1 0.003 100 -2114 -213 2010010020 ### Λb0 -> cd+ DeltaBar0 rho- +5122:addChannel = 1 0.007 100 -2224 211 2010010020 ### Λb0 -> cd+ DeltaBar-- pi+ +5122:addChannel = 1 0.003 100 -2224 213 2010010020 ### Λb0 -> cd+ DeltaBar-- rho+ +5122:addChannel = 1 0.010 0 -3122 -321 2010010020 ### Λb0 -> cd+ Lambdabar0 K- +# 31% 4 body +5122:addChannel = 1 0.054 100 -2212 111 111 2010010020 ### Λb0 -> cd+ anti-p pi0 pi0 +5122:addChannel = 1 0.027 100 -2212 211 -211 2010010020 ### Λb0 -> cd+ anti-p pi+ pi- +5122:addChannel = 1 0.013 100 -2212 213 -211 2010010020 ### Λb0 -> cd+ anti-p rho+ pi- +5122:addChannel = 1 0.018 100 -2212 113 111 2010010020 ### Λb0 -> cd+ anti-p rho0 pi0 +5122:addChannel = 1 0.009 100 -2212 113 113 2010010020 ### Λb0 -> cd+ anti-p rho0 rho0 +5122:addChannel = 1 0.018 100 -2212 221 111 2010010020 ### Λb0 -> cd+ anti-p eta pi0 +5122:addChannel = 1 0.009 100 -2212 221 113 2010010020 ### Λb0 -> cd+ anti-p eta rho0 +5122:addChannel = 1 0.018 100 -2212 223 111 2010010020 ### Λb0 -> cd+ anti-p omega pi0 +5122:addChannel = 1 0.009 100 -2212 223 113 2010010020 ### Λb0 -> cd+ anti-p omega rho0 +5122:addChannel = 1 0.040 100 -2112 -211 111 2010010020 ### Λb0 -> cd+ anti-n0 pi- pi0 +5122:addChannel = 1 0.020 100 -2112 -211 113 2010010020 ### Λb0 -> cd+ anti-n0 pi- rho0 +5122:addChannel = 1 0.020 100 -2112 -213 111 2010010020 ### Λb0 -> cd+ anti-n0 rho- pi0 +5122:addChannel = 1 0.010 100 -2112 -213 113 2010010020 ### Λb0 -> cd+ anti-n0 rho- rho0 +5122:addChannel = 1 0.010 100 -2214 111 111 2010010020 ### Λb0 -> cd+ DeltaBar- pi0 pi0 +5122:addChannel = 1 0.005 100 -2214 113 111 2010010020 ### Λb0 -> cd+ DeltaBar- rho0 pi0 +5122:addChannel = 1 0.005 100 -2214 221 111 2010010020 ### Λb0 -> cd+ DeltaBar- eta pi0 +5122:addChannel = 1 0.005 100 -2214 223 111 2010010020 ### Λb0 -> cd+ DeltaBar- omega pi0 +5122:addChannel = 1 0.007 100 -2114 -211 111 2010010020 ### Λb0 -> cd+ DeltaBar0 pi- pi0 +5122:addChannel = 1 0.003 100 -2114 -213 111 2010010020 ### Λb0 -> cd+ DeltaBar0 rho- pi0 +5122:addChannel = 1 0.007 100 -2224 211 111 2010010020 ### Λb0 -> cd+ DeltaBar-- pi+ pi0 +5122:addChannel = 1 0.003 100 -2224 213 111 2010010020 ### Λb0 -> cd+ DeltaBar-- rho+ pi0 +5122:addChannel = 1 0.010 0 -3122 -321 111 2010010020 ### Λb0 -> cd+ Lambdabar0 K- pi0 +# 19% 5 body +5122:addChannel = 1 0.033 100 -2212 111 111 111 2010010020 ### Λb0 -> cd+ anti-p pi0 pi0 pi0 +5122:addChannel = 1 0.016 100 -2212 211 -211 111 2010010020 ### Λb0 -> cd+ anti-p pi+ pi- pi0 +5122:addChannel = 1 0.008 100 -2212 213 -211 111 2010010020 ### Λb0 -> cd+ anti-p rho+ pi- pi0 +5122:addChannel = 1 0.012 100 -2212 113 111 111 2010010020 ### Λb0 -> cd+ anti-p rho0 pi0 pi0 +5122:addChannel = 1 0.006 100 -2212 113 113 111 2010010020 ### Λb0 -> cd+ anti-p rho0 rho0 pi0 +5122:addChannel = 1 0.012 100 -2212 221 111 111 2010010020 ### Λb0 -> cd+ anti-p eta pi0 pi0 +5122:addChannel = 1 0.006 100 -2212 221 113 111 2010010020 ### Λb0 -> cd+ anti-p eta rho0 pi0 +5122:addChannel = 1 0.012 100 -2212 223 111 111 2010010020 ### Λb0 -> cd+ anti-p omega pi0 pi0 +5122:addChannel = 1 0.006 100 -2212 223 113 111 2010010020 ### Λb0 -> cd+ anti-p omega rho0 pi0 +5122:addChannel = 1 0.030 100 -2112 -211 111 111 2010010020 ### Λb0 -> cd+ anti-n0 pi- pi0 pi0 +5122:addChannel = 1 0.011 100 -2112 -211 113 111 2010010020 ### Λb0 -> cd+ anti-n0 pi- rho0 pi0 +5122:addChannel = 1 0.011 100 -2112 -213 111 111 2010010020 ### Λb0 -> cd+ anti-n0 rho- pi0 pi0 +5122:addChannel = 1 0.006 100 -2112 -213 113 111 2010010020 ### Λb0 -> cd+ anti-n0 rho- rho0 pi0 +5122:addChannel = 1 0.006 100 -2214 111 111 111 2010010020 ### Λb0 -> cd+ DeltaBar- pi0 pi0 pi0 +5122:addChannel = 1 0.002 100 -2214 113 111 111 2010010020 ### Λb0 -> cd+ DeltaBar- rho0 pi0 pi0 +5122:addChannel = 1 0.002 100 -2214 221 111 111 2010010020 ### Λb0 -> cd+ DeltaBar- eta pi0 pi0 +5122:addChannel = 1 0.002 100 -2214 223 111 111 2010010020 ### Λb0 -> cd+ DeltaBar- omega pi0 pi0 +5122:addChannel = 1 0.005 100 -2114 -211 111 111 2010010020 ### Λb0 -> cd+ DeltaBar0 pi- pi0 pi0 +5122:addChannel = 1 0.001 100 -2114 -213 111 111 2010010020 ### Λb0 -> cd+ DeltaBar0 rho- pi0 pi0 +5122:addChannel = 1 0.005 100 -2224 211 111 111 2010010020 ### Λb0 -> cd+ DeltaBar-- pi+ pi0 pi0 +5122:addChannel = 1 0.001 100 -2224 213 111 111 2010010020 ### Λb0 -> cd+ DeltaBar-- rho+ pi0 pi0 +5122:addChannel = 1 0.006 0 -3122 -321 111 111 2010010020 ### Λb0 -> cd+ Lambdabar0 K- pi0 pi0 diff --git a/MC/config/common/external/generator/CoalescencePythia8.h b/MC/config/common/external/generator/CoalescencePythia8.h index b1f392ba4..7e4abc53e 100644 --- a/MC/config/common/external/generator/CoalescencePythia8.h +++ b/MC/config/common/external/generator/CoalescencePythia8.h @@ -104,7 +104,7 @@ bool doCoal(Pythia8::Event& event, int charge, int pdgCode, float mass, bool tri return true; } -bool CoalescencePythia8(Pythia8::Event& event, std::vector inputPdgList = {}, bool trivialCoal = false, double coalMomentum = 0.4, int firstDauID = -1, int lastDauId = -1) +bool CoalescencePythia8(Pythia8::Event& event, std::vector inputPdgList = {}, bool trivialCoal = false, double coalMomentum = 0.4, int firstDauID = -1, int lastDauId = -1, float maxRapidity = 1.) { const double coalescenceRadius{0.5 * 1.122462 * coalMomentum}; // if coalescence from a heavy hadron, loop only between firstDauID and lastDauID @@ -131,7 +131,7 @@ bool CoalescencePythia8(Pythia8::Event& event, std::vector inputPd // fill nucleon pools std::vector protons[2], neutrons[2], lambdas[2]; for (auto iPart{loopStart}; iPart <= loopEnd; ++iPart) { - if (std::abs(event[iPart].y()) > 1.) // skip particles with y > 1 + if (std::abs(event[iPart].y()) > maxRapidity) // skip particles with y > ymax { continue; }