From e84384a766076e8720abc6a2ce943e80264e814e Mon Sep 17 00:00:00 2001 From: mcoquet642 Date: Tue, 16 Sep 2025 11:15:20 +0200 Subject: [PATCH] Charmonium generator for pO --- .../generator/GeneratorPromptCharmonia.C | 174 ++++++++++++++++++ ...ithInjectedPromptSignals_gaptriggered_dq.C | 5 +- ...PromptCharmoniaFwdy_TriggerGap_pO96TeV.ini | 7 + ...edPromptCharmoniaFwdy_TriggerGap_pO96TeV.C | 85 +++++++++ 4 files changed, 270 insertions(+), 1 deletion(-) create mode 100755 MC/config/PWGDQ/ini/Generator_InjectedPromptCharmoniaFwdy_TriggerGap_pO96TeV.ini create mode 100644 MC/config/PWGDQ/ini/tests/Generator_InjectedPromptCharmoniaFwdy_TriggerGap_pO96TeV.C diff --git a/MC/config/PWGDQ/external/generator/GeneratorPromptCharmonia.C b/MC/config/PWGDQ/external/generator/GeneratorPromptCharmonia.C index 69deba3fa..614c9f3d1 100644 --- a/MC/config/PWGDQ/external/generator/GeneratorPromptCharmonia.C +++ b/MC/config/PWGDQ/external/generator/GeneratorPromptCharmonia.C @@ -787,6 +787,153 @@ class O2_GeneratorParamPsipp5TeV : public GeneratorTGenerator GeneratorParam* paramPsi = nullptr; }; +class O2_GeneratorParamJpsipp96TeV : public GeneratorTGenerator +{ + + public: + O2_GeneratorParamJpsipp96TeV() : GeneratorTGenerator("ParamJpsi") + { + paramJpsi = new GeneratorParam(1, -1, PtJPsipp96TeV, YJPsipp96TeV, V2JPsipp96TeV, IpJPsipp96TeV); + paramJpsi->SetMomentumRange(0., 1.e6); + paramJpsi->SetPtRange(0, 999.); + paramJpsi->SetYRange(-4.2, -2.3); + paramJpsi->SetPhiRange(0., 360.); + paramJpsi->SetDecayer(new TPythia6Decayer()); + paramJpsi->SetForceDecay(kNoDecay); // particle left undecayed + // - - paramJpsi->SetTrackingFlag(1); // (from AliGenParam) -> check this + setTGenerator(paramJpsi); + }; + + ~O2_GeneratorParamJpsipp96TeV() + { + delete paramJpsi; + }; + + Bool_t Init() override + { + GeneratorTGenerator::Init(); + paramJpsi->Init(); + return true; + } + + void SetNSignalPerEvent(Int_t nsig) { paramJpsi->SetNumberParticles(nsig); } + + //-------------------------------------------------------------------------// + static Double_t PtJPsipp96TeV(const Double_t* px, const Double_t* /*dummy*/) + { + // Parameters extrapolated linearly between 5 TeV and 13 TeV as a function of log(sqrt(s)) + Double_t x = *px; + Float_t p0, p1, p2, p3; + p0 = 1; + p1 = 4.61097; + p2 = 1.7333; + p3 = 4.45508; + return p0 * x / TMath::Power(1. + TMath::Power(x / p1, p2), p3); + } + + //-------------------------------------------------------------------------// + static Double_t YJPsipp96TeV(const Double_t* py, const Double_t* /*dummy*/) + { + // Parameters extrapolated linearly between 5 TeV and 13 TeV as a function of log(sqrt(s)) + Double_t y = *py; + Float_t p0, p1, p2; + p0 = 1; + p1 = 0.0107769; + p2 = 2.98205; + return p0 * TMath::Exp(-(1. / 2.) * TMath::Power(((y - p1) / p2), 2)); + } + + //-------------------------------------------------------------------------// + static Double_t V2JPsipp96TeV(const Double_t* /*dummy*/, const Double_t* /*dummy*/) + { + // jpsi v2 + return 0.; + } + + //-------------------------------------------------------------------------// + static Int_t IpJPsipp96TeV(TRandom*) + { + return 443; + } + + private: + GeneratorParam* paramJpsi = nullptr; +}; + +class O2_GeneratorParamPsipp96TeV : public GeneratorTGenerator +{ + + public: + O2_GeneratorParamPsipp96TeV() : GeneratorTGenerator("ParamPsi") + { + paramPsi = new GeneratorParam(1, -1, PtPsipp96TeV, YPsipp96TeV, V2Psipp96TeV, IpPsipp96TeV); + paramPsi->SetMomentumRange(0., 1.e6); + paramPsi->SetPtRange(0, 999.); + paramPsi->SetYRange(-4.2, -2.3); + paramPsi->SetPhiRange(0., 360.); + paramPsi->SetDecayer(new TPythia6Decayer()); + paramPsi->SetForceDecay(kNoDecay); // particle left undecayed + // - - paramJpsi->SetTrackingFlag(1); // check this + setTGenerator(paramPsi); + }; + + ~O2_GeneratorParamPsipp96TeV() + { + delete paramPsi; + }; + + Bool_t Init() override + { + GeneratorTGenerator::Init(); + paramPsi->Init(); + return true; + } + + void SetNSignalPerEvent(Int_t nsig) { paramPsi->SetNumberParticles(nsig); } + + //-------------------------------------------------------------------------// + static Double_t PtPsipp96TeV(const Double_t* px, const Double_t* /*dummy*/) + { + // Taking same parameters as Psi(2S) at 13 TeV + Double_t x = *px; + Float_t p0, p1, p2, p3; + p0 = 1; + p1 = 4.75208; + p2 = 1.69247; + p3 = 4.49224; + return p0 * x / TMath::Power(1. + TMath::Power(x / p1, p2), p3); + } + + //-------------------------------------------------------------------------// + static Double_t YPsipp96TeV(const Double_t* py, const Double_t* /*dummy*/) + { + // Taking same parameters as Psi(2S) at 13 TeV + Double_t y = *py; + Float_t p0, p1, p2; + p0 = 1; + p1 = 0; + p2 = 2.98887; + return p0 * TMath::Exp(-(1. / 2.) * TMath::Power(((y - p1) / p2), 2)); + } + + //-------------------------------------------------------------------------// + static Double_t V2Psipp96TeV(const Double_t* /*dummy*/, const Double_t* /*dummy*/) + { + // jpsi v2 + return 0.; + } + + //-------------------------------------------------------------------------// + static Int_t IpPsipp96TeV(TRandom*) + { + return 100443; + } + + private: + GeneratorParam* paramPsi = nullptr; +}; + + class O2_GeneratorParamJpsiPbPb5TeV : public GeneratorTGenerator { @@ -1131,6 +1278,33 @@ FairGenerator* GeneratorCocktailPromptCharmoniaToMuonEvtGen_pp5TeV() return genCocktailEvtGen; } +FairGenerator* GeneratorCocktailPromptCharmoniaToMuonEvtGen_pp96TeV() +{ + + auto genCocktailEvtGen = new o2::eventgen::GeneratorEvtGen(); + + auto genJpsi = new o2::eventgen::O2_GeneratorParamJpsipp96TeV; + genJpsi->SetNSignalPerEvent(1); // 1 J/psi generated per event by GeneratorParam + auto genPsi = new o2::eventgen::O2_GeneratorParamPsipp96TeV; + genPsi->SetNSignalPerEvent(1); // 1 Psi(2S) generated per event by GeneratorParam + genCocktailEvtGen->AddGenerator(genJpsi, 1); // add J/psi generator + genCocktailEvtGen->AddGenerator(genPsi, 1); // add Psi(2S) generator + + TString pdgs = "443;100443"; + std::string spdg; + TObjArray* obj = pdgs.Tokenize(";"); + genCocktailEvtGen->SetSizePdg(obj->GetEntriesFast()); + for (int i = 0; i < obj->GetEntriesFast(); i++) { + spdg = obj->At(i)->GetName(); + genCocktailEvtGen->AddPdg(std::stoi(spdg), i); + printf("PDG %d \n", std::stoi(spdg)); + } + genCocktailEvtGen->SetForceDecay(kEvtDiMuon); + + return genCocktailEvtGen; +} + + FairGenerator* GeneratorCocktailPromptCharmoniaToElectronEvtGen_pp5TeV() { diff --git a/MC/config/PWGDQ/external/generator/generator_pythia8_withInjectedPromptSignals_gaptriggered_dq.C b/MC/config/PWGDQ/external/generator/generator_pythia8_withInjectedPromptSignals_gaptriggered_dq.C index e58f655e9..20f763b1e 100644 --- a/MC/config/PWGDQ/external/generator/generator_pythia8_withInjectedPromptSignals_gaptriggered_dq.C +++ b/MC/config/PWGDQ/external/generator/generator_pythia8_withInjectedPromptSignals_gaptriggered_dq.C @@ -54,12 +54,15 @@ public: case 10: // generate cocktail of prompt X_1(3872) and psi2S to Jpsi pi pi at midrapidity mGeneratorParam = (Generator*)GeneratorCocktailX3872AndPsi2StoJpsi_pp13TeV(); break; - case 11: // generate cocktail of prompt X_1(3872) and psi2S to Jpsi pi pi at midrapidity + case 11: // generate prompt charmonium at forward rapidity at 5TeV mGeneratorParam = (Generator*)GeneratorCocktailPromptCharmoniaToMuonEvtGen_pp5TeV(); break; case 12: // generate prompt charmonia cocktail at mid rapidity at 5TeV mGeneratorParam = (Generator*)GeneratorCocktailPromptCharmoniaToElectronEvtGen_pp5TeV(); break; + case 13: // generate prompt charmonia cocktail at mid rapidity at 9.6TeV + mGeneratorParam = (Generator*)GeneratorCocktailPromptCharmoniaToMuonEvtGen_pp96TeV(); + break; } mGeneratorParam->Init(); } diff --git a/MC/config/PWGDQ/ini/Generator_InjectedPromptCharmoniaFwdy_TriggerGap_pO96TeV.ini b/MC/config/PWGDQ/ini/Generator_InjectedPromptCharmoniaFwdy_TriggerGap_pO96TeV.ini new file mode 100755 index 000000000..b4822ef37 --- /dev/null +++ b/MC/config/PWGDQ/ini/Generator_InjectedPromptCharmoniaFwdy_TriggerGap_pO96TeV.ini @@ -0,0 +1,7 @@ +### The external generator derives from GeneratorPythia8. +[GeneratorExternal] +fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGDQ/external/generator/generator_pythia8_withInjectedPromptSignals_gaptriggered_dq.C +funcName=GeneratorPythia8InjectedPromptCharmoniaGapTriggered(5,13) + +[GeneratorPythia8] +config=${O2DPG_MC_CONFIG_ROOT}/MC/config/common/pythia8/generator/pythia8_pO_961.cfg diff --git a/MC/config/PWGDQ/ini/tests/Generator_InjectedPromptCharmoniaFwdy_TriggerGap_pO96TeV.C b/MC/config/PWGDQ/ini/tests/Generator_InjectedPromptCharmoniaFwdy_TriggerGap_pO96TeV.C new file mode 100644 index 000000000..5dd26f49d --- /dev/null +++ b/MC/config/PWGDQ/ini/tests/Generator_InjectedPromptCharmoniaFwdy_TriggerGap_pO96TeV.C @@ -0,0 +1,85 @@ +int External() +{ + int checkPdgSignal[] = {443,100443}; + int checkPdgDecay = 13; + double rapiditymin = -4.3; double rapiditymax = -2.3; + std::string path{"o2sim_Kine.root"}; + std::cout << "Check for\nsignal PDG " << checkPdgSignal << "\ndecay PDG " << checkPdgDecay << "\n"; + 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 nLeptons{}; + int nAntileptons{}; + int nLeptonPairs{}; + int nLeptonPairsToBeDone{}; + int nSignalJpsi{}; + int nSignalPsi2S{}; + int nSignalJpsiWithinAcc{}; + int nSignalPsi2SWithinAcc{}; + auto nEvents = tree->GetEntries(); + o2::steer::MCKinematicsReader mcreader("o2sim", o2::steer::MCKinematicsReader::Mode::kMCKine); + Bool_t isInjected = kFALSE; + + for (int i = 0; i < nEvents; i++) { + tree->GetEntry(i); + for (auto& track : *tracks) { + auto pdg = track.GetPdgCode(); + auto rapidity = track.GetRapidity(); + auto idMoth = track.getMotherTrackId(); + if (pdg == checkPdgDecay) { + // count leptons + nLeptons++; + } else if(pdg == -checkPdgDecay) { + // count anti-leptons + nAntileptons++; + } else if (pdg == checkPdgSignal[0] || pdg == checkPdgSignal[1]) { + if(idMoth < 0) { + // count signal PDG + pdg == checkPdgSignal[0] ? nSignalJpsi++ : nSignalPsi2S++; + // count signal PDG within acceptance + if(rapidity > rapiditymin && rapidity < rapiditymax) { pdg == checkPdgSignal[0] ? nSignalJpsiWithinAcc++ : nSignalPsi2SWithinAcc++;} + } + auto child0 = o2::mcutils::MCTrackNavigator::getDaughter0(track, *tracks); + auto child1 = o2::mcutils::MCTrackNavigator::getDaughter1(track, *tracks); + if (child0 != nullptr && child1 != nullptr) { + // check for parent-child relations + auto pdg0 = child0->GetPdgCode(); + auto pdg1 = child1->GetPdgCode(); + std::cout << "First and last children of parent " << checkPdgSignal << " are PDG0: " << pdg0 << " PDG1: " << pdg1 << "\n"; + if (std::abs(pdg0) == checkPdgDecay && std::abs(pdg1) == checkPdgDecay && pdg0 == -pdg1) { + nLeptonPairs++; + if (child0->getToBeDone() && child1->getToBeDone()) { + nLeptonPairsToBeDone++; + } + } + } + } + } + } + std::cout << "#events: " << nEvents << "\n" + << "#leptons: " << nLeptons << "\n" + << "#antileptons: " << nAntileptons << "\n" + << "#signal (prompt Jpsi): " << nSignalJpsi << "; within acceptance " << rapiditymin << " < y < " << rapiditymax << " : " << nSignalJpsiWithinAcc << "\n" + << "#signal (prompt Psi(2S)): " << nSignalPsi2S << "; within acceptance " << rapiditymin << " < y < " << rapiditymax << " : " << nSignalPsi2SWithinAcc << "\n" + << "#lepton pairs: " << nLeptonPairs << "\n" + << "#lepton pairs to be done: " << nLeptonPairs << "\n"; + + + if (nLeptonPairs == 0 || nLeptons == 0 || nAntileptons == 0) { + std::cerr << "Number of leptons, number of anti-leptons as well as number of lepton pairs should all be greater than 1.\n"; + return 1; + } + if (nLeptonPairs != nLeptonPairsToBeDone) { + std::cerr << "The number of lepton pairs should be the same as the number of lepton pairs which should be transported.\n"; + return 1; + } + + return 0; +}