Skip to content

Commit a06ad26

Browse files
author
Bong-Hwi Lim
committed
[PWGLF] Add single-channel K1(1270) and Omega(2012) injection configs for ML signal samples
One stratum (charge x decay channel) per job: one injected parent per pp 13.6 TeV inelastic event, no gap, |y| < 0.7, flat pT (K1: 0-8 GeV/c, Omega(2012): 0-15 GeV/c), finite-width sampling with generator_pythia8_LF_rapidity_width.C. - K1(1270)+-: K rho0 (rho0 -> pi+ pi-) and K*(892) pi (K* -> K pi) - Omega(2012)-+: Xi K0S and Xi(1530)0 K (Xi(1530)0 -> Xi pi) The forced-decay tables are new files; resonances_width.cfg and the existing recipes are unchanged. Branching fractions are forced to unity and must be weighted in the analysis. Xi, Lambda and K0S are decayed by the transport code with their natural branching fractions. Each INI redirects to a per-channel test that requires exactly one injected parent per event and the forced chain for both charges; parents produced in the underlying event are counted but not checked.
1 parent 8e2fcba commit a06ad26

24 files changed

Lines changed: 628 additions & 0 deletions
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#---> GeneratorLF_ResonancesML_K1_KstarPi_pp1360
2+
# Single-channel ML signal sample: one K1(1270)- per pp 13.6 TeV inelastic event (no gap), flat pT 0-8 GeV/c,
3+
# |y| < 0.7, forced decay chain from resonance_ml_k1_kstarpi.cfg. One stratum (charge x channel) per job.
4+
[GeneratorExternal]
5+
fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator_pythia8_LF_rapidity_width.C
6+
funcName=generateLFRapidity("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/resonancegun_ml_k1minus_kstarpi.json", true, 0, false, true, "${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/pythia8_inel_136tev.cfg", "")
7+
8+
[GeneratorPythia8] # if triggered then this will be used as the background event
9+
config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/pythia8_inel_136tev.cfg
10+
11+
[DecayerPythia8] # after for transport code!
12+
config[0]=${O2DPG_MC_CONFIG_ROOT}/MC/config/common/pythia8/decayer/base.cfg
13+
config[1]=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/resonance_ml_k1_kstarpi.cfg
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#---> GeneratorLF_ResonancesML_K1_RhoK_pp1360
2+
# Single-channel ML signal sample: one K1(1270)- per pp 13.6 TeV inelastic event (no gap), flat pT 0-8 GeV/c,
3+
# |y| < 0.7, forced decay chain from resonance_ml_k1_rhok.cfg. One stratum (charge x channel) per job.
4+
[GeneratorExternal]
5+
fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator_pythia8_LF_rapidity_width.C
6+
funcName=generateLFRapidity("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/resonancegun_ml_k1minus_rhok.json", true, 0, false, true, "${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/pythia8_inel_136tev.cfg", "")
7+
8+
[GeneratorPythia8] # if triggered then this will be used as the background event
9+
config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/pythia8_inel_136tev.cfg
10+
11+
[DecayerPythia8] # after for transport code!
12+
config[0]=${O2DPG_MC_CONFIG_ROOT}/MC/config/common/pythia8/decayer/base.cfg
13+
config[1]=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/resonance_ml_k1_rhok.cfg
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#---> GeneratorLF_ResonancesML_K1_KstarPi_pp1360
2+
# Single-channel ML signal sample: one K1(1270)+ per pp 13.6 TeV inelastic event (no gap), flat pT 0-8 GeV/c,
3+
# |y| < 0.7, forced decay chain from resonance_ml_k1_kstarpi.cfg. One stratum (charge x channel) per job.
4+
[GeneratorExternal]
5+
fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator_pythia8_LF_rapidity_width.C
6+
funcName=generateLFRapidity("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/resonancegun_ml_k1plus_kstarpi.json", true, 0, false, true, "${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/pythia8_inel_136tev.cfg", "")
7+
8+
[GeneratorPythia8] # if triggered then this will be used as the background event
9+
config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/pythia8_inel_136tev.cfg
10+
11+
[DecayerPythia8] # after for transport code!
12+
config[0]=${O2DPG_MC_CONFIG_ROOT}/MC/config/common/pythia8/decayer/base.cfg
13+
config[1]=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/resonance_ml_k1_kstarpi.cfg
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#---> GeneratorLF_ResonancesML_K1_RhoK_pp1360
2+
# Single-channel ML signal sample: one K1(1270)+ per pp 13.6 TeV inelastic event (no gap), flat pT 0-8 GeV/c,
3+
# |y| < 0.7, forced decay chain from resonance_ml_k1_rhok.cfg. One stratum (charge x channel) per job.
4+
[GeneratorExternal]
5+
fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator_pythia8_LF_rapidity_width.C
6+
funcName=generateLFRapidity("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/resonancegun_ml_k1plus_rhok.json", true, 0, false, true, "${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/pythia8_inel_136tev.cfg", "")
7+
8+
[GeneratorPythia8] # if triggered then this will be used as the background event
9+
config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/pythia8_inel_136tev.cfg
10+
11+
[DecayerPythia8] # after for transport code!
12+
config[0]=${O2DPG_MC_CONFIG_ROOT}/MC/config/common/pythia8/decayer/base.cfg
13+
config[1]=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/resonance_ml_k1_rhok.cfg
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#---> GeneratorLF_ResonancesML_Omega2012_Xi1530K_pp1360
2+
# Single-channel ML signal sample: one Omega(2012)- per pp 13.6 TeV inelastic event (no gap), flat pT 0-15 GeV/c,
3+
# |y| < 0.7, forced decay chain from resonance_ml_omega2012_xi1530k.cfg. One stratum (charge x channel) per job.
4+
[GeneratorExternal]
5+
fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator_pythia8_LF_rapidity_width.C
6+
funcName=generateLFRapidity("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/resonancegun_ml_omega2012minus_xi1530k.json", true, 0, false, true, "${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/pythia8_inel_136tev.cfg", "")
7+
8+
[GeneratorPythia8] # if triggered then this will be used as the background event
9+
config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/pythia8_inel_136tev.cfg
10+
11+
[DecayerPythia8] # after for transport code!
12+
config[0]=${O2DPG_MC_CONFIG_ROOT}/MC/config/common/pythia8/decayer/base.cfg
13+
config[1]=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/resonance_ml_omega2012_xi1530k.cfg
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#---> GeneratorLF_ResonancesML_Omega2012_XiK0s_pp1360
2+
# Single-channel ML signal sample: one Omega(2012)- per pp 13.6 TeV inelastic event (no gap), flat pT 0-15 GeV/c,
3+
# |y| < 0.7, forced decay chain from resonance_ml_omega2012_xik0s.cfg. One stratum (charge x channel) per job.
4+
[GeneratorExternal]
5+
fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator_pythia8_LF_rapidity_width.C
6+
funcName=generateLFRapidity("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/resonancegun_ml_omega2012minus_xik0s.json", true, 0, false, true, "${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/pythia8_inel_136tev.cfg", "")
7+
8+
[GeneratorPythia8] # if triggered then this will be used as the background event
9+
config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/pythia8_inel_136tev.cfg
10+
11+
[DecayerPythia8] # after for transport code!
12+
config[0]=${O2DPG_MC_CONFIG_ROOT}/MC/config/common/pythia8/decayer/base.cfg
13+
config[1]=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/resonance_ml_omega2012_xik0s.cfg
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#---> GeneratorLF_ResonancesML_Omega2012_Xi1530K_pp1360
2+
# Single-channel ML signal sample: one Omega(2012)+ per pp 13.6 TeV inelastic event (no gap), flat pT 0-15 GeV/c,
3+
# |y| < 0.7, forced decay chain from resonance_ml_omega2012_xi1530k.cfg. One stratum (charge x channel) per job.
4+
[GeneratorExternal]
5+
fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator_pythia8_LF_rapidity_width.C
6+
funcName=generateLFRapidity("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/resonancegun_ml_omega2012plus_xi1530k.json", true, 0, false, true, "${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/pythia8_inel_136tev.cfg", "")
7+
8+
[GeneratorPythia8] # if triggered then this will be used as the background event
9+
config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/pythia8_inel_136tev.cfg
10+
11+
[DecayerPythia8] # after for transport code!
12+
config[0]=${O2DPG_MC_CONFIG_ROOT}/MC/config/common/pythia8/decayer/base.cfg
13+
config[1]=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/resonance_ml_omega2012_xi1530k.cfg
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#---> GeneratorLF_ResonancesML_Omega2012_XiK0s_pp1360
2+
# Single-channel ML signal sample: one Omega(2012)+ per pp 13.6 TeV inelastic event (no gap), flat pT 0-15 GeV/c,
3+
# |y| < 0.7, forced decay chain from resonance_ml_omega2012_xik0s.cfg. One stratum (charge x channel) per job.
4+
[GeneratorExternal]
5+
fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator_pythia8_LF_rapidity_width.C
6+
funcName=generateLFRapidity("${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/resonancegun_ml_omega2012plus_xik0s.json", true, 0, false, true, "${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/pythia8_inel_136tev.cfg", "")
7+
8+
[GeneratorPythia8] # if triggered then this will be used as the background event
9+
config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/pythia8_inel_136tev.cfg
10+
11+
[DecayerPythia8] # after for transport code!
12+
config[0]=${O2DPG_MC_CONFIG_ROOT}/MC/config/common/pythia8/decayer/base.cfg
13+
config[1]=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/resonance_ml_omega2012_xik0s.cfg
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
// Test of the single-channel ML signal samples GeneratorLF_ResonancesML_*_pp1360.ini that redirect here.
2+
// Every event carries exactly one injected parent (no gap); the parent and the intermediate resonances decayed by the
3+
// generator must follow the forced chain (charge conjugated for the negative-PDG parent). Parents with a mother come
4+
// from the underlying Pythia event, decay with the default table, and are only counted.
5+
int External()
6+
{
7+
const std::string path{"o2sim_Kine.root"};
8+
const int parentPDG{10323};
9+
const std::vector<int> daughtersOfPositive{313, 211};
10+
const std::map<int, std::vector<int>> intermediateDecaysOfPositive{{313, {321, -211}}};
11+
const std::set<int> selfConjugate{111, 113, 310};
12+
auto conjugate = [&](int pdg, int sign) { return (sign > 0 || selfConjugate.count(pdg)) ? pdg : -pdg; };
13+
auto sorted = [](std::vector<int> v) { std::sort(v.begin(), v.end()); return v; };
14+
15+
TFile file(path.c_str(), "READ");
16+
if (file.IsZombie()) {
17+
std::cerr << "Cannot open ROOT file " << path << "\n";
18+
return 1;
19+
}
20+
auto tree = (TTree*)file.Get("o2sim");
21+
if (!tree) {
22+
std::cerr << "Cannot find tree o2sim in file " << path << "\n";
23+
return 1;
24+
}
25+
std::vector<o2::MCTrack>* tracks{};
26+
tree->SetBranchAddress("MCTrack", &tracks);
27+
28+
int nEventsWrongParentCount{0}, nFromUnderlyingEvent{0}, nParents{0}, nNotDecayed{0}, nWrongDecay{0}, nIntermediates{0}, nWrongIntermediate{0};
29+
std::map<int, int> nParentsBySign;
30+
for (Long64_t i = 0; i < tree->GetEntries(); ++i) {
31+
tree->GetEntry(i);
32+
int nParentsInEvent{0};
33+
for (const auto& track : *tracks) {
34+
const int pdg = track.GetPdgCode();
35+
if (std::abs(pdg) != parentPDG) {
36+
continue;
37+
}
38+
if (track.getMotherTrackId() >= 0) {
39+
++nFromUnderlyingEvent;
40+
continue;
41+
}
42+
++nParentsInEvent;
43+
++nParents;
44+
const int sign = pdg > 0 ? 1 : -1;
45+
++nParentsBySign[sign];
46+
if (track.getFirstDaughterTrackId() < 0) {
47+
++nNotDecayed;
48+
continue;
49+
}
50+
std::vector<int> expected, found;
51+
for (int d : daughtersOfPositive) {
52+
expected.push_back(conjugate(d, sign));
53+
}
54+
for (int j = track.getFirstDaughterTrackId(); j <= track.getLastDaughterTrackId(); ++j) {
55+
const auto& daughter = tracks->at(j);
56+
found.push_back(daughter.GetPdgCode());
57+
const auto it = intermediateDecaysOfPositive.find(sign > 0 ? daughter.GetPdgCode() : conjugate(daughter.GetPdgCode(), -1));
58+
if (it == intermediateDecaysOfPositive.end()) {
59+
continue;
60+
}
61+
++nIntermediates;
62+
std::vector<int> expectedGrand, foundGrand;
63+
for (int g : it->second) {
64+
expectedGrand.push_back(conjugate(g, sign));
65+
}
66+
for (int k = daughter.getFirstDaughterTrackId(); k >= 0 && k <= daughter.getLastDaughterTrackId(); ++k) {
67+
foundGrand.push_back(tracks->at(k).GetPdgCode());
68+
}
69+
if (sorted(expectedGrand) != sorted(foundGrand)) {
70+
++nWrongIntermediate;
71+
}
72+
}
73+
if (sorted(expected) != sorted(found)) {
74+
++nWrongDecay;
75+
}
76+
}
77+
if (nParentsInEvent != 1) {
78+
++nEventsWrongParentCount;
79+
}
80+
}
81+
82+
std::cout << "--------------------------------\n";
83+
std::cout << "# Events: " << tree->GetEntries() << "\n";
84+
std::cout << "# Parents " << parentPDG << ": " << nParentsBySign[1] << ", anti: " << nParentsBySign[-1] << "\n";
85+
std::cout << "# Parents from the underlying event (not checked): " << nFromUnderlyingEvent << "\n";
86+
std::cout << "# Events without exactly one parent: " << nEventsWrongParentCount << "\n";
87+
std::cout << "# Parents not decayed: " << nNotDecayed << ", with wrong daughters: " << nWrongDecay << "\n";
88+
std::cout << "# Intermediate resonances: " << nIntermediates << ", with wrong daughters: " << nWrongIntermediate << "\n";
89+
std::cout << "--------------------------------\n";
90+
if (tree->GetEntries() == 0 || nEventsWrongParentCount || nNotDecayed || nWrongDecay || nWrongIntermediate ||
91+
(!intermediateDecaysOfPositive.empty() && nIntermediates != nParents)) {
92+
std::cerr << "Forced decay chain not reproduced\n";
93+
return 1;
94+
}
95+
return 0;
96+
}
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
// Test of the single-channel ML signal samples GeneratorLF_ResonancesML_*_pp1360.ini that redirect here.
2+
// Every event carries exactly one injected parent (no gap); the parent and the intermediate resonances decayed by the
3+
// generator must follow the forced chain (charge conjugated for the negative-PDG parent). Parents with a mother come
4+
// from the underlying Pythia event, decay with the default table, and are only counted.
5+
int External()
6+
{
7+
const std::string path{"o2sim_Kine.root"};
8+
const int parentPDG{10323};
9+
const std::vector<int> daughtersOfPositive{321, 113};
10+
const std::map<int, std::vector<int>> intermediateDecaysOfPositive{{113, {211, -211}}};
11+
const std::set<int> selfConjugate{111, 113, 310};
12+
auto conjugate = [&](int pdg, int sign) { return (sign > 0 || selfConjugate.count(pdg)) ? pdg : -pdg; };
13+
auto sorted = [](std::vector<int> v) { std::sort(v.begin(), v.end()); return v; };
14+
15+
TFile file(path.c_str(), "READ");
16+
if (file.IsZombie()) {
17+
std::cerr << "Cannot open ROOT file " << path << "\n";
18+
return 1;
19+
}
20+
auto tree = (TTree*)file.Get("o2sim");
21+
if (!tree) {
22+
std::cerr << "Cannot find tree o2sim in file " << path << "\n";
23+
return 1;
24+
}
25+
std::vector<o2::MCTrack>* tracks{};
26+
tree->SetBranchAddress("MCTrack", &tracks);
27+
28+
int nEventsWrongParentCount{0}, nFromUnderlyingEvent{0}, nParents{0}, nNotDecayed{0}, nWrongDecay{0}, nIntermediates{0}, nWrongIntermediate{0};
29+
std::map<int, int> nParentsBySign;
30+
for (Long64_t i = 0; i < tree->GetEntries(); ++i) {
31+
tree->GetEntry(i);
32+
int nParentsInEvent{0};
33+
for (const auto& track : *tracks) {
34+
const int pdg = track.GetPdgCode();
35+
if (std::abs(pdg) != parentPDG) {
36+
continue;
37+
}
38+
if (track.getMotherTrackId() >= 0) {
39+
++nFromUnderlyingEvent;
40+
continue;
41+
}
42+
++nParentsInEvent;
43+
++nParents;
44+
const int sign = pdg > 0 ? 1 : -1;
45+
++nParentsBySign[sign];
46+
if (track.getFirstDaughterTrackId() < 0) {
47+
++nNotDecayed;
48+
continue;
49+
}
50+
std::vector<int> expected, found;
51+
for (int d : daughtersOfPositive) {
52+
expected.push_back(conjugate(d, sign));
53+
}
54+
for (int j = track.getFirstDaughterTrackId(); j <= track.getLastDaughterTrackId(); ++j) {
55+
const auto& daughter = tracks->at(j);
56+
found.push_back(daughter.GetPdgCode());
57+
const auto it = intermediateDecaysOfPositive.find(sign > 0 ? daughter.GetPdgCode() : conjugate(daughter.GetPdgCode(), -1));
58+
if (it == intermediateDecaysOfPositive.end()) {
59+
continue;
60+
}
61+
++nIntermediates;
62+
std::vector<int> expectedGrand, foundGrand;
63+
for (int g : it->second) {
64+
expectedGrand.push_back(conjugate(g, sign));
65+
}
66+
for (int k = daughter.getFirstDaughterTrackId(); k >= 0 && k <= daughter.getLastDaughterTrackId(); ++k) {
67+
foundGrand.push_back(tracks->at(k).GetPdgCode());
68+
}
69+
if (sorted(expectedGrand) != sorted(foundGrand)) {
70+
++nWrongIntermediate;
71+
}
72+
}
73+
if (sorted(expected) != sorted(found)) {
74+
++nWrongDecay;
75+
}
76+
}
77+
if (nParentsInEvent != 1) {
78+
++nEventsWrongParentCount;
79+
}
80+
}
81+
82+
std::cout << "--------------------------------\n";
83+
std::cout << "# Events: " << tree->GetEntries() << "\n";
84+
std::cout << "# Parents " << parentPDG << ": " << nParentsBySign[1] << ", anti: " << nParentsBySign[-1] << "\n";
85+
std::cout << "# Parents from the underlying event (not checked): " << nFromUnderlyingEvent << "\n";
86+
std::cout << "# Events without exactly one parent: " << nEventsWrongParentCount << "\n";
87+
std::cout << "# Parents not decayed: " << nNotDecayed << ", with wrong daughters: " << nWrongDecay << "\n";
88+
std::cout << "# Intermediate resonances: " << nIntermediates << ", with wrong daughters: " << nWrongIntermediate << "\n";
89+
std::cout << "--------------------------------\n";
90+
if (tree->GetEntries() == 0 || nEventsWrongParentCount || nNotDecayed || nWrongDecay || nWrongIntermediate ||
91+
(!intermediateDecaysOfPositive.empty() && nIntermediates != nParents)) {
92+
std::cerr << "Forced decay chain not reproduced\n";
93+
return 1;
94+
}
95+
return 0;
96+
}

0 commit comments

Comments
 (0)