Skip to content

Commit 3b4b041

Browse files
authored
[PWGEM/Dilepton] update HFee in MC for flavor oscillation (#13635)
1 parent e7cacf2 commit 3b4b041

File tree

1 file changed

+108
-21
lines changed

1 file changed

+108
-21
lines changed

PWGEM/Dilepton/Utils/MCUtilities.h

Lines changed: 108 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -295,7 +295,86 @@ int IsFromCharm(TMCParticle const& p, TMCParticles const& mcparticles)
295295

296296
return -999;
297297
}
298+
//_______________________________________________________________________
299+
template <typename TMCParticle, typename TMCParticles>
300+
bool findFlavorOscillationB(TMCParticle const& mcParticle, TMCParticles const& mcParticles)
301+
{
302+
// B0 or B0s can oscillate.
303+
if (!mcParticle.has_mothers()) {
304+
return false;
305+
}
306+
307+
// store all mother1 relation
308+
int motherid1 = mcParticle.mothersIds()[0]; // first mother index
309+
while (motherid1 > -1) {
310+
if (motherid1 < mcParticles.size()) { // protect against bad mother indices. why is this needed?
311+
auto mp = mcParticles.iteratorAt(motherid1);
312+
if ((std::abs(mp.pdgCode()) == 511 || std::abs(mp.pdgCode()) == 531) && mp.getGenStatusCode() == 92) {
313+
return true;
314+
}
298315

316+
if (mp.has_mothers()) {
317+
motherid1 = mp.mothersIds()[0];
318+
} else {
319+
motherid1 = -999;
320+
}
321+
} else {
322+
LOGF(info, "Mother label(%d) exceeds the McParticles size(%d)", motherid1, mcParticles.size());
323+
}
324+
}
325+
return false;
326+
}
327+
//_______________________________________________________________________
328+
template <typename TMCParticle, typename TMCParticles>
329+
int find1stHadron(TMCParticle const& mcParticle, TMCParticles const& mcParticles)
330+
{
331+
// find 1st hadron in decay chain except beam.
332+
if (!mcParticle.has_mothers()) {
333+
return -1;
334+
}
335+
336+
// store all mother1 relation
337+
std::vector<int> mothers_id;
338+
std::vector<int> mothers_pdg;
339+
340+
int motherid1 = mcParticle.mothersIds()[0]; // first mother index
341+
while (motherid1 > -1) {
342+
if (motherid1 < mcParticles.size()) { // protect against bad mother indices. why is this needed?
343+
auto mp = mcParticles.iteratorAt(motherid1);
344+
mothers_id.emplace_back(motherid1);
345+
mothers_pdg.emplace_back(mp.pdgCode());
346+
347+
if (mp.has_mothers()) {
348+
motherid1 = mp.mothersIds()[0];
349+
} else {
350+
motherid1 = -999;
351+
}
352+
} else {
353+
LOGF(info, "Mother label(%d) exceeds the McParticles size(%d)", motherid1, mcParticles.size());
354+
}
355+
}
356+
357+
int counter = 0;
358+
for (const auto& pdg : mothers_pdg) {
359+
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
360+
break;
361+
}
362+
counter++;
363+
}
364+
365+
int hadronId = -1;
366+
if (counter == 0) { // particle directly from beam // only for protection.
367+
hadronId = mcParticle.globalIndex();
368+
} else {
369+
hadronId = mothers_id[counter - 1];
370+
}
371+
372+
mothers_id.clear();
373+
mothers_id.shrink_to_fit();
374+
mothers_pdg.clear();
375+
mothers_pdg.shrink_to_fit();
376+
return hadronId;
377+
}
299378
//_______________________________________________________________________
300379
template <typename TMCParticle1, typename TMCParticle2, typename TMCParticles>
301380
int IsHF(TMCParticle1 const& p1, TMCParticle2 const& p2, TMCParticles const& mcparticles)
@@ -318,6 +397,7 @@ int IsHF(TMCParticle1 const& p1, TMCParticle2 const& p2, TMCParticles const& mcp
318397
mothers_id1.emplace_back(motherid1);
319398
mothers_pdg1.emplace_back(mp.pdgCode());
320399
// LOGF(info, "mp1.globalIndex() = %d, mp1.pdgCode() = %d, mp1.getGenStatusCode() = %d", mp.globalIndex(), mp.pdgCode(), mp.getGenStatusCode());
400+
321401
if (mp.has_mothers()) {
322402
motherid1 = mp.mothersIds()[0];
323403
} else {
@@ -351,14 +431,19 @@ int IsHF(TMCParticle1 const& p1, TMCParticle2 const& p2, TMCParticles const& mcp
351431

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

434+
auto mpfh1 = mcparticles.iteratorAt(find1stHadron(p1, mcparticles));
435+
auto mpfh2 = mcparticles.iteratorAt(find1stHadron(p2, mcparticles));
436+
bool isFOFound1 = findFlavorOscillationB(p1, mcparticles);
437+
bool isFOFound2 = findFlavorOscillationB(p2, mcparticles);
438+
354439
bool is_direct_from_b1 = IsFromBeauty(p1, mcparticles) > 0 && IsFromCharm(p1, mcparticles) < 0;
355440
bool is_direct_from_b2 = IsFromBeauty(p2, mcparticles) > 0 && IsFromCharm(p2, mcparticles) < 0;
356441
bool is_prompt_c1 = IsFromBeauty(p1, mcparticles) < 0 && IsFromCharm(p1, mcparticles) > 0;
357442
bool is_prompt_c2 = IsFromBeauty(p2, mcparticles) < 0 && IsFromCharm(p2, mcparticles) > 0;
358443
bool is_c_from_b1 = IsFromBeauty(p1, mcparticles) > 0 && IsFromCharm(p1, mcparticles) > 0;
359444
bool is_c_from_b2 = IsFromBeauty(p2, mcparticles) > 0 && IsFromCharm(p2, mcparticles) > 0;
360445

361-
if (is_direct_from_b1 && is_direct_from_b2) {
446+
if (is_prompt_c1 && is_prompt_c2 && mpfh1.pdgCode() * mpfh2.pdgCode() < 0) { // charmed mesons never oscillate. only ULS
362447
mothers_id1.clear();
363448
mothers_pdg1.clear();
364449
mothers_id2.clear();
@@ -367,9 +452,14 @@ int IsHF(TMCParticle1 const& p1, TMCParticle2 const& p2, TMCParticles const& mcp
367452
mothers_pdg1.shrink_to_fit();
368453
mothers_id2.shrink_to_fit();
369454
mothers_pdg2.shrink_to_fit();
370-
return static_cast<int>(EM_HFeeType::kBe_Be); // bb->ee, decay type = 2
455+
return static_cast<int>(EM_HFeeType::kCe_Ce); // cc->ee, decay type = 0
371456
}
372-
if (is_prompt_c1 && is_prompt_c2) {
457+
458+
bool b2l_b2l_case0 = is_direct_from_b1 && is_direct_from_b2 && mpfh1.pdgCode() * mpfh2.pdgCode() < 0 && !isFOFound1 && !isFOFound2; // 0 oscillation: bbbar -> ll ULS
459+
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
460+
bool b2l_b2l_case2 = is_direct_from_b1 && is_direct_from_b2 && mpfh1.pdgCode() * mpfh2.pdgCode() < 0 && isFOFound1 && isFOFound2; // 2 oscillation: bbbar -> ll ULS
461+
462+
if (b2l_b2l_case0 || b2l_b2l_case1 || b2l_b2l_case2) {
373463
mothers_id1.clear();
374464
mothers_pdg1.clear();
375465
mothers_id2.clear();
@@ -378,9 +468,14 @@ int IsHF(TMCParticle1 const& p1, TMCParticle2 const& p2, TMCParticles const& mcp
378468
mothers_pdg1.shrink_to_fit();
379469
mothers_id2.shrink_to_fit();
380470
mothers_pdg2.shrink_to_fit();
381-
return static_cast<int>(EM_HFeeType::kCe_Ce); // cc->ee, decay type = 0
471+
return static_cast<int>(EM_HFeeType::kBe_Be); // bb->ee, decay type = 2
382472
}
383-
if (is_c_from_b1 && is_c_from_b2) {
473+
474+
bool b2c2l_b2c2l_case0 = is_c_from_b1 && is_c_from_b2 && mpfh1.pdgCode() * mpfh2.pdgCode() < 0 && !isFOFound1 && !isFOFound2; // 0 oscillation: bbbar -> ll ULS
475+
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
476+
bool b2c2l_b2c2l_case2 = is_c_from_b1 && is_c_from_b2 && mpfh1.pdgCode() * mpfh2.pdgCode() < 0 && isFOFound1 && isFOFound2; // 2 oscillation: bbbar -> ll ULS
477+
478+
if (b2c2l_b2c2l_case0 || b2c2l_b2c2l_case1 || b2c2l_b2c2l_case2) {
384479
mothers_id1.clear();
385480
mothers_pdg1.clear();
386481
mothers_id2.clear();
@@ -391,7 +486,9 @@ int IsHF(TMCParticle1 const& p1, TMCParticle2 const& p2, TMCParticles const& mcp
391486
mothers_pdg2.shrink_to_fit();
392487
return static_cast<int>(EM_HFeeType::kBCe_BCe); // b->c->e and b->c->e, decay type = 1
393488
}
489+
394490
if ((is_direct_from_b1 && is_c_from_b2) || (is_direct_from_b2 && is_c_from_b1)) {
491+
// No pair sign oscillation due to B0(s) oscillation for the same mother.
395492
for (const auto& mid1 : mothers_id1) {
396493
for (const auto& mid2 : mothers_id2) {
397494
if (mid1 == mid2) {
@@ -413,20 +510,11 @@ int IsHF(TMCParticle1 const& p1, TMCParticle2 const& p2, TMCParticles const& mcp
413510
} // end of motherid2
414511
} // end of motherid1
415512

416-
bool is_same_mother_found = false;
417-
for (const auto& mid1 : mothers_id1) {
418-
for (const auto& mid2 : mothers_id2) {
419-
if (mid1 == mid2) {
420-
auto common_mp = mcparticles.iteratorAt(mid1);
421-
int mp_pdg = common_mp.pdgCode();
422-
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';
423-
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')) {
424-
is_same_mother_found = true;
425-
}
426-
}
427-
} // end of motherid2
428-
} // end of motherid1
429-
if (!is_same_mother_found) {
513+
bool b2c2l_b2l_diffb_case0 = mpfh1.pdgCode() * mpfh2.pdgCode() > 0 && !isFOFound1 && !isFOFound2; // 0 oscillation: bbbar -> ll LS
514+
bool b2c2l_b2l_diffb_case1 = mpfh1.pdgCode() * mpfh2.pdgCode() < 0 && static_cast<bool>(isFOFound1 ^ isFOFound2); // 1 oscillation: bbbar -> ll ULS
515+
bool b2c2l_b2l_diffb_case2 = mpfh1.pdgCode() * mpfh2.pdgCode() > 0 && isFOFound1 && isFOFound2; // 2 oscillation: bbbar -> ll LS
516+
517+
if (b2c2l_b2l_diffb_case0 || b2c2l_b2l_diffb_case1 || b2c2l_b2l_diffb_case2) {
430518
mothers_id1.clear();
431519
mothers_pdg1.clear();
432520
mothers_id2.clear();
@@ -435,7 +523,7 @@ int IsHF(TMCParticle1 const& p1, TMCParticle2 const& p2, TMCParticles const& mcp
435523
mothers_pdg1.shrink_to_fit();
436524
mothers_id2.shrink_to_fit();
437525
mothers_pdg2.shrink_to_fit();
438-
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
526+
return static_cast<int>(EM_HFeeType::kBCe_Be_DiffB); // b->c->e and b->e, decay type = 4. this should happen only in LS.
439527
}
440528
}
441529

@@ -449,7 +537,6 @@ int IsHF(TMCParticle1 const& p1, TMCParticle2 const& p2, TMCParticles const& mcp
449537
mothers_pdg2.shrink_to_fit();
450538
return static_cast<int>(EM_HFeeType::kUndef);
451539
}
452-
453540
//_______________________________________________________________________
454541
template <typename T, typename U>
455542
int searchMothers(T& p, U& mcParticles, int pdg, bool equal)

0 commit comments

Comments
 (0)