Skip to content

Commit 70179ce

Browse files
committed
Add test macro and change lifetime from 1 mm to 0.5 mm
1 parent e71700c commit 70179ce

4 files changed

Lines changed: 144 additions & 10 deletions

File tree

MC/config/PWGHF/external/generator/generator_pythia8_embed_charmnuclei.C

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,15 @@ class GeneratorPythia8HFEmbedCharmNuclei : public o2::eventgen::GeneratorPythia8
3636
LOG(fatal) << "********** [GeneratorPythia8HFEmbedCharmNuclei] Only c-deuteron (pdg=2010010020) currently supported! Exit **********";
3737
}
3838
mLifetimeCharmNucleus = lifetime;
39-
mDecayDistr = new TF1("mDecayDistr", Form("exp(-x/%f)", mLifetimeCharmNucleus), 0., 1000.);
40-
mDecayDistrLb = new TF1("mDecayDistrLb", "exp(-x/0.440)", 0., 1000.);
41-
mPtDistrLb = new TF1("mPtDistrLb","[0]*x/TMath::Power((1+TMath::Power(x/[1],[3])),[2])",0.,1000.);
39+
mDecayDistr = new TF1("mDecayDistr", "TMath::Exp(-x * 1./[0])", 0., mLifetimeCharmNucleus * 100);
40+
mDecayDistr->SetNpx(10000);
41+
mDecayDistr->SetParameter(0, mLifetimeCharmNucleus);
42+
mDecayDistrLb = new TF1("mDecayDistrLb", "TMath::Exp(-x * 1./[0])", 0., 44.f);
43+
mDecayDistrLb->SetParameter(0, 0.440f); // lifetime of Lambda_b in mm/c
44+
mDecayDistrLb->SetNpx(10000);
45+
mPtDistrLb = new TF1("mPtDistrLb","[0]*x/TMath::Power((1+TMath::Power(x/[1],[3])),[2])",0.,100.);
4246
mPtDistrLb->SetParameters(1000., 6.97355, 3.20721, 1.71678);
47+
mPtDistrLb->SetNpx(10000);
4348

4449
Print();
4550

@@ -114,7 +119,7 @@ class GeneratorPythia8HFEmbedCharmNuclei : public o2::eventgen::GeneratorPythia8
114119

115120
int pdgToGen = mPdgCharmNucleus;
116121
float massToGen = mMassCharmNucleus;
117-
float lifetimeToGen = mDecayDistr->GetRandom();
122+
float lifetimeToGen = 0.f;
118123
float minRapToGen = mRapidityMinCharmNuclei;
119124
float maxRapToGen = mRapidityMaxCharmNuclei;
120125
bool isFromB = gRandom->Rndm() < mFractionFromBeauty;
@@ -125,6 +130,8 @@ class GeneratorPythia8HFEmbedCharmNuclei : public o2::eventgen::GeneratorPythia8
125130
lifetimeToGen = mDecayDistrLb->GetRandom();
126131
minRapToGen *= 2;
127132
maxRapToGen *= 2;
133+
} else {
134+
lifetimeToGen = mDecayDistr->GetRandom();
128135
}
129136

130137
auto pt = (!isFromB) ? gRandom->Uniform(0., mPtMaxCharmNuclei) : mPtDistrLb->GetRandom();
@@ -244,16 +251,16 @@ class GeneratorPythia8HFEmbedCharmNuclei : public o2::eventgen::GeneratorPythia8
244251
auto daughter1 = part.daughter1();
245252
auto daughter2 = part.daughter2();
246253
if (mother1 > 0) {
247-
part.mother1(mother1 + offset);
254+
part.mother1(mother1 + offset - 1);
248255
}
249256
if (mother2 > 0) {
250-
part.mother2(mother2 + offset);
257+
part.mother2(mother2 + offset - 1);
251258
}
252259
if (daughter1 > 0) {
253-
part.daughter1(daughter1 + offset);
260+
part.daughter1(daughter1 + offset - 1);
254261
}
255262
if (daughter2 > 0) {
256-
part.daughter2(daughter2 + offset);
263+
part.daughter2(daughter2 + offset - 1);
257264
}
258265
mPythia.event.append(part);
259266
}

MC/config/PWGHF/ini/GeneratorHF_CDeuteron_Injected.ini

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
### The external generator derives from GeneratorPythia8.
33
[GeneratorExternal]
44
fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGHF/external/generator/generator_pythia8_embed_charmnuclei.C
5-
funcName=GenerateHFEmbedCDeuteron(1., 10, -1., 1., 25., 0, 0.4, 0.25)
5+
funcName=GenerateHFEmbedCDeuteron(0.5, 10, -1., 1., 25., 0, 0.4, 0.25)
66

77
### includePartonEvent is needed to keep the c-deuteron in the event record, even if there are no partons in the event
88
[GeneratorPythia8]
Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
int External() {
2+
std::string path{"o2sim_Kine.root"};
3+
4+
int pdgCDeuteron{2010010020};
5+
int checkNumberOfCDeuteronPerEvent{10};
6+
float checkLifetimeCDeuteron{0.05f};
7+
std::map<int, std::vector<std::vector<int>>> checkDecays{
8+
{2010010020, {{-321, 211, 1000010020}}} // c-deuteron -> K- + pi+ + deuteron
9+
};
10+
float checkFracCDeuteronFromBeauty{0.25};
11+
12+
TFile file(path.c_str(), "READ");
13+
if (file.IsZombie()) {
14+
std::cerr << "Cannot open ROOT file " << path << "\n";
15+
return 1;
16+
}
17+
18+
auto tree = (TTree *)file.Get("o2sim");
19+
std::vector<o2::MCTrack> *tracks{};
20+
tree->SetBranchAddress("MCTrack", &tracks);
21+
22+
int nCDeuteron{}, nCDeuteronGoodDecay{}, nCDeuteronFromBeauty{};
23+
std::array<float, 2> averageLifetimeCDeuteron{0.f, 0.f}; // prompt and non-prompt
24+
float massCDeuteron = 3.226f;
25+
auto nEvents = tree->GetEntries();
26+
27+
for (int i = 0; i < nEvents; i++) {
28+
tree->GetEntry(i);
29+
30+
for (auto &track : *tracks) {
31+
auto pdg = track.GetPdgCode();
32+
auto absPdg = std::abs(pdg);
33+
// std::cout << "Event " << i << ": found particle with PDG " << pdg << std::endl;
34+
35+
if (absPdg == pdgCDeuteron) { // found signal
36+
nCDeuteron++; // count signal PDG
37+
38+
// std::cout << "Event " << i << ": found c-deuteron with PDG " << pdg << std::endl;
39+
40+
std::vector<int> pdgsDecay{};
41+
std::vector<int> pdgsDecayAntiPart{};
42+
if (track.getFirstDaughterTrackId() >= 0 && track.getLastDaughterTrackId() >= 0) {
43+
for (int j{track.getFirstDaughterTrackId()}; j <= track.getLastDaughterTrackId(); ++j) {
44+
// std::cout << "Fetching daughter track with ID " << j << std::endl;
45+
auto pdgDau = tracks->at(j).GetPdgCode();
46+
// std::cout << "PDG of daughter track " << j << ": " << pdgDau << std::endl;
47+
pdgsDecay.push_back(pdgDau);
48+
if (pdgDau != 333 && pdgDau != 111) { // phi and pi0 are antiparticles of themselves
49+
pdgsDecayAntiPart.push_back(-pdgDau);
50+
} else {
51+
pdgsDecayAntiPart.push_back(pdgDau);
52+
}
53+
}
54+
}
55+
// std::cout << "Daughters fetched" << std::endl;
56+
57+
auto mother = track.getMotherTrackId();
58+
bool isFromBeauty{false};
59+
if (mother >= 0 && std::abs(tracks->at(mother).GetPdgCode()) == 5122) { // check if c-deuteron comes from Lb
60+
nCDeuteronFromBeauty++;
61+
isFromBeauty = true;
62+
}
63+
64+
auto dauTrack = tracks->at(track.getFirstDaughterTrackId());
65+
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()));
66+
if (!isFromBeauty) {
67+
averageLifetimeCDeuteron[0] += decayLength * massCDeuteron / track.GetP();
68+
} else {
69+
averageLifetimeCDeuteron[1] += decayLength * massCDeuteron / track.GetP();
70+
}
71+
72+
std::sort(pdgsDecay.begin(), pdgsDecay.end());
73+
std::sort(pdgsDecayAntiPart.begin(), pdgsDecayAntiPart.end());
74+
75+
for (auto &decay : checkDecays[std::abs(pdg)]) {
76+
if (pdgsDecay == decay || pdgsDecayAntiPart == decay) {
77+
nCDeuteronGoodDecay++;
78+
break;
79+
}
80+
}
81+
// std::cout << "Daughters checked " << std::endl;
82+
}
83+
}
84+
}
85+
86+
averageLifetimeCDeuteron[0] /= nCDeuteron - nCDeuteronFromBeauty;
87+
averageLifetimeCDeuteron[1] /= nCDeuteronFromBeauty;
88+
89+
std::cout << "--------------------------------\n";
90+
std::cout << "# Events: " << nEvents << "\n";
91+
std::cout <<"# signal c-deuteron: " << nCDeuteron << "\n";
92+
std::cout <<"# signal c-deuteron decaying in the correct channel: " << nCDeuteronGoodDecay << "\n";
93+
std::cout <<"# signal c-deuteron from beauty: " << nCDeuteronFromBeauty << "\n";
94+
std::cout <<"Average lifetime of c-deuteron (prompt): " << averageLifetimeCDeuteron[0] << " (cm) \n";
95+
std::cout <<"Average lifetime of c-deuteron (non-prompt): " << averageLifetimeCDeuteron[1] << " (cm) \n";
96+
97+
float numberOfCDeuteronPerEvent = float(nCDeuteron) / nEvents;
98+
float fracCDeuteronGoodDecay = float(nCDeuteronGoodDecay) / nCDeuteron;
99+
float fracCDeuteronFromBeauty = float(nCDeuteronFromBeauty) / nCDeuteron;
100+
101+
if (std::abs(numberOfCDeuteronPerEvent - checkNumberOfCDeuteronPerEvent) / numberOfCDeuteronPerEvent > 0.05) { // we put some tolerance since the number of generated events is small
102+
std::cerr << "Number of C-deuterons per event " << numberOfCDeuteronPerEvent << " different than expected " << checkNumberOfCDeuteronPerEvent << "\n";
103+
return 1;
104+
}
105+
106+
if (fracCDeuteronGoodDecay < 0.95) { // we put some tolerance since the number of generated events is small
107+
std::cerr << "Fraction of signals decaying into the correct channel " << fracCDeuteronGoodDecay << " lower than expected\n";
108+
return 1;
109+
}
110+
111+
if (std::abs(fracCDeuteronFromBeauty - checkFracCDeuteronFromBeauty) / checkFracCDeuteronFromBeauty > 0.10) { // we put some tolerance since the number of generated events is small
112+
std::cerr << "Fraction of signals from beauty " << fracCDeuteronFromBeauty << " different than expected " << checkFracCDeuteronFromBeauty << "\n";
113+
return 1;
114+
}
115+
116+
if (std::abs(averageLifetimeCDeuteron[0] - checkLifetimeCDeuteron) / checkLifetimeCDeuteron > 0.10) { // we put some tolerance since the number of generated events is small
117+
std::cerr << "Lifetime for prompt c-deuteron " << averageLifetimeCDeuteron[0] << " different than expected " << checkLifetimeCDeuteron << "\n";
118+
return 1;
119+
}
120+
121+
if (std::abs(averageLifetimeCDeuteron[1] - checkLifetimeCDeuteron) / checkLifetimeCDeuteron > 0.10) { // we put some tolerance since the number of generated events is small
122+
std::cerr << "Lifetime for non-prompt c-deuteron " << averageLifetimeCDeuteron[1] << " different than expected " << checkLifetimeCDeuteron << "\n";
123+
return 1;
124+
}
125+
126+
return 0;
127+
}

MC/config/PWGHF/pythia8/generator/pythia8_cdeuteron_to_dkpi.cfg

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ ParticleDecays:tau0Max 10.
1515

1616
### add the c-deuteron
1717
### id:all = name antiName spinType chargeType colType m0 mWidth mMin mMax tau0
18-
2010010020:all = CDeuteron AntiCDeuteron 1 3 0 3.226 0 3.226 3.226 1.
18+
2010010020:all = CDeuteron AntiCDeuteron 1 3 0 3.226 0 3.226 3.226 0.5
1919
2010010020:mayDecay = on
2020

2121
# same as Λc+ -> p K- π+ including resonances + a neutron

0 commit comments

Comments
 (0)