@@ -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// _______________________________________________________________________
300379template <typename TMCParticle1, typename TMCParticle2, typename TMCParticles>
301380int 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// _______________________________________________________________________
454541template <typename T, typename U>
455542int searchMothers (T& p, U& mcParticles, int pdg, bool equal)
0 commit comments