Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
129 changes: 108 additions & 21 deletions PWGEM/Dilepton/Utils/MCUtilities.h
Original file line number Diff line number Diff line change
Expand Up @@ -241,14 +241,14 @@

int motherid = p.mothersIds()[0]; // first mother index
auto mp_tmp = mcparticles.iteratorAt(motherid);
if (std::abs(mp_tmp.pdgCode()) < 1e+9 && (std::to_string(std::abs(mp_tmp.pdgCode()))[std::to_string(std::abs(mp_tmp.pdgCode())).length() - 2] == '5' && std::to_string(std::abs(mp_tmp.pdgCode()))[std::to_string(std::abs(mp_tmp.pdgCode())).length() - 3] == '5') && std::abs(mp_tmp.pdgCode()) % 2 == 1) {

Check failure on line 244 in PWGEM/Dilepton/Utils/MCUtilities.h

View workflow job for this annotation

GitHub Actions / O2 linter

[magic-number]

Avoid magic numbers in expressions. Assign the value to a clearly named variable or constant.
return -999; // reject bottomonia
}

while (motherid > -1) {
if (motherid < mcparticles.size()) { // protect against bad mother indices. why is this needed?
auto mp = mcparticles.iteratorAt(motherid);
if (std::abs(mp.pdgCode()) < 1e+9 && (std::to_string(std::abs(mp.pdgCode()))[std::to_string(std::abs(mp.pdgCode())).length() - 3] == '5' || std::to_string(std::abs(mp.pdgCode()))[std::to_string(std::abs(mp.pdgCode())).length() - 4] == '5')) {

Check failure on line 251 in PWGEM/Dilepton/Utils/MCUtilities.h

View workflow job for this annotation

GitHub Actions / O2 linter

[magic-number]

Avoid magic numbers in expressions. Assign the value to a clearly named variable or constant.
return motherid;
}
if (mp.has_mothers()) {
Expand All @@ -274,13 +274,13 @@

int motherid = p.mothersIds()[0]; // first mother index
auto mp_tmp = mcparticles.iteratorAt(motherid);
if (std::abs(mp_tmp.pdgCode()) < 1e+9 && (std::to_string(std::abs(mp_tmp.pdgCode()))[std::to_string(std::abs(mp_tmp.pdgCode())).length() - 2] == '4' && std::to_string(std::abs(mp_tmp.pdgCode()))[std::to_string(std::abs(mp_tmp.pdgCode())).length() - 3] == '4') && std::abs(mp_tmp.pdgCode()) % 2 == 1) {

Check failure on line 277 in PWGEM/Dilepton/Utils/MCUtilities.h

View workflow job for this annotation

GitHub Actions / O2 linter

[magic-number]

Avoid magic numbers in expressions. Assign the value to a clearly named variable or constant.
return -999; // reject bottomonia
}
while (motherid > -1) {
if (motherid < mcparticles.size()) { // protect against bad mother indices. why is this needed?
auto mp = mcparticles.iteratorAt(motherid);
if (std::abs(mp.pdgCode()) < 1e+9 && (std::to_string(std::abs(mp.pdgCode()))[std::to_string(std::abs(mp.pdgCode())).length() - 3] == '4' || std::to_string(std::abs(mp.pdgCode()))[std::to_string(std::abs(mp.pdgCode())).length() - 4] == '4')) {

Check failure on line 283 in PWGEM/Dilepton/Utils/MCUtilities.h

View workflow job for this annotation

GitHub Actions / O2 linter

[magic-number]

Avoid magic numbers in expressions. Assign the value to a clearly named variable or constant.
return motherid;
}
if (mp.has_mothers()) {
Expand All @@ -295,7 +295,86 @@

return -999;
}
//_______________________________________________________________________
template <typename TMCParticle, typename TMCParticles>
bool findFlavorOscillationB(TMCParticle const& mcParticle, TMCParticles const& mcParticles)
{
// B0 or B0s can oscillate.
if (!mcParticle.has_mothers()) {
return false;
}

// store all mother1 relation
int motherid1 = mcParticle.mothersIds()[0]; // first mother index
while (motherid1 > -1) {
if (motherid1 < mcParticles.size()) { // protect against bad mother indices. why is this needed?
auto mp = mcParticles.iteratorAt(motherid1);
if ((std::abs(mp.pdgCode()) == 511 || std::abs(mp.pdgCode()) == 531) && mp.getGenStatusCode() == 92) {

Check failure on line 312 in PWGEM/Dilepton/Utils/MCUtilities.h

View workflow job for this annotation

GitHub Actions / O2 linter

[magic-number]

Avoid magic numbers in expressions. Assign the value to a clearly named variable or constant.

Check failure on line 312 in PWGEM/Dilepton/Utils/MCUtilities.h

View workflow job for this annotation

GitHub Actions / O2 linter

[pdg/explicit-code]

Avoid hard-coded PDG codes. Use named values from PDG_t or o2::constants::physics::Pdg instead.
return true;
}

if (mp.has_mothers()) {
motherid1 = mp.mothersIds()[0];
} else {
motherid1 = -999;
}
} else {
LOGF(info, "Mother label(%d) exceeds the McParticles size(%d)", motherid1, mcParticles.size());
}
}
return false;
}
//_______________________________________________________________________
template <typename TMCParticle, typename TMCParticles>
int find1stHadron(TMCParticle const& mcParticle, TMCParticles const& mcParticles)
{
// find 1st hadron in decay chain except beam.
if (!mcParticle.has_mothers()) {
return -1;
}

// store all mother1 relation
std::vector<int> mothers_id;
std::vector<int> mothers_pdg;

int motherid1 = mcParticle.mothersIds()[0]; // first mother index
while (motherid1 > -1) {
if (motherid1 < mcParticles.size()) { // protect against bad mother indices. why is this needed?
auto mp = mcParticles.iteratorAt(motherid1);
mothers_id.emplace_back(motherid1);
mothers_pdg.emplace_back(mp.pdgCode());

if (mp.has_mothers()) {
motherid1 = mp.mothersIds()[0];
} else {
motherid1 = -999;
}
} else {
LOGF(info, "Mother label(%d) exceeds the McParticles size(%d)", motherid1, mcParticles.size());
}
}

int counter = 0;
for (const auto& pdg : mothers_pdg) {
if (std::abs(pdg) <= 6 || std::abs(pdg) == 21 || (std::abs(pdg) == 2212 && counter == static_cast<int>(mothers_pdg.size() - 1)) || (std::abs(pdg) > 1e+9 && counter == static_cast<int>(mothers_pdg.size() - 1))) { // quarks or gluon or proton or ion beam

Check failure on line 359 in PWGEM/Dilepton/Utils/MCUtilities.h

View workflow job for this annotation

GitHub Actions / O2 linter

[magic-number]

Avoid magic numbers in expressions. Assign the value to a clearly named variable or constant.

Check failure on line 359 in PWGEM/Dilepton/Utils/MCUtilities.h

View workflow job for this annotation

GitHub Actions / O2 linter

[pdg/explicit-code]

Avoid hard-coded PDG codes. Use named values from PDG_t or o2::constants::physics::Pdg instead.
break;
}
counter++;
}

int hadronId = -1;
if (counter == 0) { // particle directly from beam // only for protection.
hadronId = mcParticle.globalIndex();
} else {
hadronId = mothers_id[counter - 1];
}

mothers_id.clear();
mothers_id.shrink_to_fit();
mothers_pdg.clear();
mothers_pdg.shrink_to_fit();
return hadronId;
}
//_______________________________________________________________________
template <typename TMCParticle1, typename TMCParticle2, typename TMCParticles>
int IsHF(TMCParticle1 const& p1, TMCParticle2 const& p2, TMCParticles const& mcparticles)
Expand All @@ -318,6 +397,7 @@
mothers_id1.emplace_back(motherid1);
mothers_pdg1.emplace_back(mp.pdgCode());
// LOGF(info, "mp1.globalIndex() = %d, mp1.pdgCode() = %d, mp1.getGenStatusCode() = %d", mp.globalIndex(), mp.pdgCode(), mp.getGenStatusCode());

if (mp.has_mothers()) {
motherid1 = mp.mothersIds()[0];
} else {
Expand Down Expand Up @@ -351,14 +431,19 @@

// require correlation between q-qbar. (not q-q) // need statusCode

auto mpfh1 = mcparticles.iteratorAt(find1stHadron(p1, mcparticles));
auto mpfh2 = mcparticles.iteratorAt(find1stHadron(p2, mcparticles));
bool isFOFound1 = findFlavorOscillationB(p1, mcparticles);
bool isFOFound2 = findFlavorOscillationB(p2, mcparticles);

bool is_direct_from_b1 = IsFromBeauty(p1, mcparticles) > 0 && IsFromCharm(p1, mcparticles) < 0;
bool is_direct_from_b2 = IsFromBeauty(p2, mcparticles) > 0 && IsFromCharm(p2, mcparticles) < 0;
bool is_prompt_c1 = IsFromBeauty(p1, mcparticles) < 0 && IsFromCharm(p1, mcparticles) > 0;
bool is_prompt_c2 = IsFromBeauty(p2, mcparticles) < 0 && IsFromCharm(p2, mcparticles) > 0;
bool is_c_from_b1 = IsFromBeauty(p1, mcparticles) > 0 && IsFromCharm(p1, mcparticles) > 0;
bool is_c_from_b2 = IsFromBeauty(p2, mcparticles) > 0 && IsFromCharm(p2, mcparticles) > 0;

if (is_direct_from_b1 && is_direct_from_b2) {
if (is_prompt_c1 && is_prompt_c2 && mpfh1.pdgCode() * mpfh2.pdgCode() < 0) { // charmed mesons never oscillate. only ULS
mothers_id1.clear();
mothers_pdg1.clear();
mothers_id2.clear();
Expand All @@ -367,9 +452,14 @@
mothers_pdg1.shrink_to_fit();
mothers_id2.shrink_to_fit();
mothers_pdg2.shrink_to_fit();
return static_cast<int>(EM_HFeeType::kBe_Be); // bb->ee, decay type = 2
return static_cast<int>(EM_HFeeType::kCe_Ce); // cc->ee, decay type = 0
}
if (is_prompt_c1 && is_prompt_c2) {

bool b2l_b2l_case0 = is_direct_from_b1 && is_direct_from_b2 && mpfh1.pdgCode() * mpfh2.pdgCode() < 0 && !isFOFound1 && !isFOFound2; // 0 oscillation: bbbar -> ll ULS
bool b2l_b2l_case1 = is_direct_from_b1 && is_direct_from_b2 && mpfh1.pdgCode() * mpfh2.pdgCode() > 0 && static_cast<bool>(isFOFound1 ^ isFOFound2); // 1 oscillation: bbbar -> ll LS
bool b2l_b2l_case2 = is_direct_from_b1 && is_direct_from_b2 && mpfh1.pdgCode() * mpfh2.pdgCode() < 0 && isFOFound1 && isFOFound2; // 2 oscillation: bbbar -> ll ULS

if (b2l_b2l_case0 || b2l_b2l_case1 || b2l_b2l_case2) {
mothers_id1.clear();
mothers_pdg1.clear();
mothers_id2.clear();
Expand All @@ -378,9 +468,14 @@
mothers_pdg1.shrink_to_fit();
mothers_id2.shrink_to_fit();
mothers_pdg2.shrink_to_fit();
return static_cast<int>(EM_HFeeType::kCe_Ce); // cc->ee, decay type = 0
return static_cast<int>(EM_HFeeType::kBe_Be); // bb->ee, decay type = 2
}
if (is_c_from_b1 && is_c_from_b2) {

bool b2c2l_b2c2l_case0 = is_c_from_b1 && is_c_from_b2 && mpfh1.pdgCode() * mpfh2.pdgCode() < 0 && !isFOFound1 && !isFOFound2; // 0 oscillation: bbbar -> ll ULS
bool b2c2l_b2c2l_case1 = is_c_from_b1 && is_c_from_b2 && mpfh1.pdgCode() * mpfh2.pdgCode() > 0 && static_cast<bool>(isFOFound1 ^ isFOFound2); // 1 oscillation: bbbar -> ll LS
bool b2c2l_b2c2l_case2 = is_c_from_b1 && is_c_from_b2 && mpfh1.pdgCode() * mpfh2.pdgCode() < 0 && isFOFound1 && isFOFound2; // 2 oscillation: bbbar -> ll ULS

if (b2c2l_b2c2l_case0 || b2c2l_b2c2l_case1 || b2c2l_b2c2l_case2) {
mothers_id1.clear();
mothers_pdg1.clear();
mothers_id2.clear();
Expand All @@ -391,7 +486,9 @@
mothers_pdg2.shrink_to_fit();
return static_cast<int>(EM_HFeeType::kBCe_BCe); // b->c->e and b->c->e, decay type = 1
}

if ((is_direct_from_b1 && is_c_from_b2) || (is_direct_from_b2 && is_c_from_b1)) {
// No pair sign oscillation due to B0(s) oscillation for the same mother.
for (const auto& mid1 : mothers_id1) {
for (const auto& mid2 : mothers_id2) {
if (mid1 == mid2) {
Expand All @@ -413,20 +510,11 @@
} // end of motherid2
} // end of motherid1

bool is_same_mother_found = false;
for (const auto& mid1 : mothers_id1) {
for (const auto& mid2 : mothers_id2) {
if (mid1 == mid2) {
auto common_mp = mcparticles.iteratorAt(mid1);
int mp_pdg = common_mp.pdgCode();
bool is_mp_diquark = (1100 < std::abs(mp_pdg) && std::abs(mp_pdg) < 5600) && std::to_string(mp_pdg)[std::to_string(mp_pdg).length() - 2] == '0';
if (!is_mp_diquark && std::abs(mp_pdg) < 1e+9 && (std::to_string(std::abs(mp_pdg))[std::to_string(std::abs(mp_pdg)).length() - 3] == '5' || std::to_string(std::abs(mp_pdg))[std::to_string(std::abs(mp_pdg)).length() - 4] == '5')) {
is_same_mother_found = true;
}
}
} // end of motherid2
} // end of motherid1
if (!is_same_mother_found) {
bool b2c2l_b2l_diffb_case0 = mpfh1.pdgCode() * mpfh2.pdgCode() > 0 && !isFOFound1 && !isFOFound2; // 0 oscillation: bbbar -> ll LS
bool b2c2l_b2l_diffb_case1 = mpfh1.pdgCode() * mpfh2.pdgCode() < 0 && static_cast<bool>(isFOFound1 ^ isFOFound2); // 1 oscillation: bbbar -> ll ULS
bool b2c2l_b2l_diffb_case2 = mpfh1.pdgCode() * mpfh2.pdgCode() > 0 && isFOFound1 && isFOFound2; // 2 oscillation: bbbar -> ll LS

if (b2c2l_b2l_diffb_case0 || b2c2l_b2l_diffb_case1 || b2c2l_b2l_diffb_case2) {
mothers_id1.clear();
mothers_pdg1.clear();
mothers_id2.clear();
Expand All @@ -435,7 +523,7 @@
mothers_pdg1.shrink_to_fit();
mothers_id2.shrink_to_fit();
mothers_pdg2.shrink_to_fit();
return static_cast<int>(EM_HFeeType::kBCe_Be_DiffB); // b->c->e and b->e, decay type = 4. this should happen only in LS. But, this may happen, when ele/pos is reconstructed as pos/ele wrongly. and create LS pair
return static_cast<int>(EM_HFeeType::kBCe_Be_DiffB); // b->c->e and b->e, decay type = 4. this should happen only in LS.
}
}

Expand All @@ -449,7 +537,6 @@
mothers_pdg2.shrink_to_fit();
return static_cast<int>(EM_HFeeType::kUndef);
}

//_______________________________________________________________________
template <typename T, typename U>
int searchMothers(T& p, U& mcParticles, int pdg, bool equal)
Expand Down Expand Up @@ -482,7 +569,7 @@
if (equal) { // we are searching for the quark
int quark_id = -1;
int next_mother_id = -1;
for (int i : allmothersids) {

Check failure on line 572 in PWGEM/Dilepton/Utils/MCUtilities.h

View workflow job for this annotation

GitHub Actions / O2 linter

[const-ref-in-for-loop]

Use constant references for non-modified iterators in range-based for loops.
auto mother = mcParticles.iteratorAt(i);
int mpdg = mother.pdgCode();
// if (std::abs(mpdg) == pdg && mpdg * p.pdgCode() > 0) { // check for quark
Expand Down Expand Up @@ -511,7 +598,7 @@
return -1;
} else { // searching for first ancestor that is not quark anymore
int quark_id = -1;
for (int i : allmothersids) {

Check failure on line 601 in PWGEM/Dilepton/Utils/MCUtilities.h

View workflow job for this annotation

GitHub Actions / O2 linter

[const-ref-in-for-loop]

Use constant references for non-modified iterators in range-based for loops.
auto mother = mcParticles.iteratorAt(i);
int mpdg = std::abs(mother.pdgCode());
if (mpdg == pdg && mother.pdgCode() == p.pdgCode()) { // found the quark
Expand Down
Loading