Skip to content

Commit 84277d3

Browse files
fchinualibuild
andauthored
[Common,PWGHF] Add reduced workflow for B+, B0s -> J/Psi X analyses (#11368)
Co-authored-by: ALICE Action Bot <alibuild@cern.ch>
1 parent ff7830b commit 84277d3

21 files changed

+4141
-142
lines changed

Common/Core/RecoDecay.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include <array> // std::array
2323
#include <cmath> // std::abs, std::sqrt
2424
#include <cstdio>
25+
#include <tuple> // std::apply
2526
#include <utility> // std::move
2627
#include <vector> // std::vector
2728

@@ -285,6 +286,19 @@ struct RecoDecay {
285286
return static_cast<double>(length) * static_cast<double>(mass) / p(mom);
286287
}
287288

289+
/// Calculates proper lifetime times c (pseudoproper decay length) in XY from information on daughter tracks.
290+
/// \param posPV {x, y, z} or {x, y} position of the primary vertex
291+
/// \param posSV {x, y, z} or {x, y} position of the secondary vertex
292+
/// \param mom array of {x, y, z} or {x, y} momentum arrays of the decay products
293+
/// \param mass mass of the decay products
294+
/// \return pseudoproper decay length
295+
template <std::size_t N, std::size_t NM, typename T, typename U, typename V, typename M>
296+
static double ctXY(const T& posPV, const U& posSV, const std::array<std::array<V, NM>, N>& mom, const std::array<M, N> mass)
297+
{
298+
// c t_xy = l_xy * m c^2 / (pT c)
299+
return distanceXY(posPV, posSV) * m(mom, mass) / std::apply([](const auto&... args) { return pt(args...); }, mom);
300+
}
301+
288302
/// Calculates cosine of θ* (theta star).
289303
/// \note Implemented for 2 prongs only.
290304
/// \param arrMom array of two 3-momentum arrays

PWGHF/Core/DecayChannels.h

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,30 @@ enum DecayChannelResonant : int8_t {
174174
//
175175
LastChannelResonant
176176
};
177+
/// @brief beauty candidates: beauty to J/ψ decay channels
178+
enum DecayChannelToJpsiMain : int8_t {
179+
// B0
180+
B0ToJpsiPiK = 1, // J/ψ π- K+
181+
// Bs0
182+
BsToJpsiKK, // J/ψ K+ K-
183+
// Λb0
184+
LbToJpsiPK, // J/ψ p K-
185+
// B+
186+
BplusToJpsiK, // J/ψ K+
187+
// Bc+
188+
BcToJpsiPi, // J/ψ π+
189+
//
190+
LastChannelToJpsiMain
191+
};
192+
/// @brief beauty candidates: beauty to J/ψ resonant decay channels
193+
enum DecayChannelToJpsiResonant : int8_t {
194+
// B0
195+
B0ToJpsiKstar0 = 1, // J/ψ K*0(892)
196+
// Bs0
197+
BsToJpsiPhi, // J/ψ φ
198+
//
199+
LastChannelToJpsiResonant
200+
};
177201
} // namespace hf_cand_beauty
178202
} // namespace o2::hf_decay
179203

PWGHF/Core/HfHelper.h

Lines changed: 233 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -17,21 +17,21 @@
1717
#ifndef PWGHF_CORE_HFHELPER_H_
1818
#define PWGHF_CORE_HFHELPER_H_
1919

20-
#include <Math/GenVector/Boost.h>
21-
#include <Math/Vector4D.h> // IWYU pragma: keep (do not replace with Math/Vector4Dfwd.h)
20+
#include "PWGHF/Utils/utilsAnalysis.h"
21+
22+
#include "Common/Core/RecoDecay.h"
23+
#include "Common/Core/TrackSelectorPID.h"
2224

2325
#include <CommonConstants/MathConstants.h>
2426
#include <CommonConstants/PhysicsConstants.h>
2527

28+
#include <Math/GenVector/Boost.h>
29+
#include <Math/Vector4D.h> // IWYU pragma: keep (do not replace with Math/Vector4Dfwd.h)
30+
2631
#include <array>
2732
#include <cmath>
2833
#include <vector>
2934

30-
#include "Common/Core/RecoDecay.h"
31-
#include "Common/Core/TrackSelectorPID.h"
32-
33-
#include "PWGHF/Utils/utilsAnalysis.h"
34-
3535
class HfHelper
3636
{
3737
public:
@@ -173,6 +173,12 @@ class HfHelper
173173
return candidate.m(std::array{o2::constants::physics::MassD0, o2::constants::physics::MassPiPlus});
174174
}
175175

176+
template <typename T>
177+
auto invMassBplusToJpsiK(const T& candidate)
178+
{
179+
return candidate.m(std::array{o2::constants::physics::MassMuon, o2::constants::physics::MassMuon, o2::constants::physics::MassKPlus});
180+
}
181+
176182
template <typename T>
177183
auto cosThetaStarBplus(const T& candidate)
178184
{
@@ -659,6 +665,12 @@ class HfHelper
659665
return candidate.m(std::array{o2::constants::physics::MassDSBar, o2::constants::physics::MassPiPlus});
660666
}
661667

668+
template <typename T>
669+
auto invMassBsToJpsiPhi(const T& candidate)
670+
{
671+
return candidate.m(std::array{o2::constants::physics::MassMuon, o2::constants::physics::MassMuon, o2::constants::physics::MassKPlus, o2::constants::physics::MassKPlus});
672+
}
673+
662674
template <typename T>
663675
auto cosThetaStarBs(const T& candidate)
664676
{
@@ -784,8 +796,7 @@ class HfHelper
784796
/// \param pidTrackPi PID status of trackPi (prong1 of B0 candidate)
785797
/// \param acceptPIDNotApplicable switch to accept Status::NotApplicable
786798
/// \return true if prong1 of B0 candidate passes all selections
787-
template <typename T1 = int, typename T2 = bool>
788-
bool selectionB0ToDPiPid(const T1& pidTrackPi, const T2& acceptPIDNotApplicable)
799+
bool selectionB0ToDPiPid(const int pidTrackPi, const bool acceptPIDNotApplicable)
789800
{
790801
if (!acceptPIDNotApplicable && pidTrackPi != TrackSelectorPID::Accepted) {
791802
return false;
@@ -805,10 +816,10 @@ class HfHelper
805816
template <typename T1, typename T2, typename T3>
806817
bool selectionBplusToD0PiTopol(const T1& candBp, const T2& cuts, const T3& binsPt)
807818
{
808-
auto ptcandBp = candBp.pt();
819+
auto ptCandBp = candBp.pt();
809820
auto ptPi = RecoDecay::pt(candBp.pxProng1(), candBp.pyProng1());
810821

811-
int pTBin = o2::analysis::findBin(binsPt, ptcandBp);
822+
int pTBin = o2::analysis::findBin(binsPt, ptCandBp);
812823
if (pTBin == -1) {
813824
return false;
814825
}
@@ -860,8 +871,7 @@ class HfHelper
860871
/// \param pidTrackPi PID status of trackPi (prong1 of B+ candidate)
861872
/// \param acceptPIDNotApplicable switch to accept Status::NotApplicable
862873
/// \return true if prong1 of B+ candidate passes all selections
863-
template <typename T1 = int, typename T2 = bool>
864-
bool selectionBplusToD0PiPid(const T1& pidTrackPi, const T2& acceptPIDNotApplicable)
874+
bool selectionBplusToD0PiPid(const int pidTrackPi, const bool acceptPIDNotApplicable)
865875
{
866876
if (!acceptPIDNotApplicable && pidTrackPi != TrackSelectorPID::Accepted) {
867877
return false;
@@ -873,6 +883,105 @@ class HfHelper
873883
return true;
874884
}
875885

886+
// Apply topological cuts as defined in SelectorCuts.h
887+
/// \param candBp B+ candidate
888+
/// \param cuts B+ candidate selection per pT bin
889+
/// \param binsPt pT bin limits
890+
/// \return true if candidate passes all selections
891+
template <typename T1, typename T2, typename T3>
892+
bool selectionBplusToJpsiKTopol(const T1& candBp, const T2& cuts, const T3& binsPt)
893+
{
894+
auto ptCandBp = candBp.pt();
895+
auto mCandBp = invMassBplusToJpsiK(candBp);
896+
auto ptJpsi = RecoDecay::pt(candBp.pxProng0(), candBp.pyProng0());
897+
auto ptKa = RecoDecay::pt(candBp.pxProng1(), candBp.pyProng1());
898+
auto candJpsi = candBp.jpsi();
899+
float pseudoPropDecLen = candBp.decayLengthXY() * mCandBp / ptCandBp;
900+
901+
int binPt = o2::analysis::findBin(binsPt, ptCandBp);
902+
if (binPt == -1) {
903+
return false;
904+
}
905+
906+
// B+ mass cut
907+
if (std::abs(mCandBp - o2::constants::physics::MassBPlus) > cuts->get(binPt, "m")) {
908+
return false;
909+
}
910+
911+
// kaon pt
912+
if (ptKa < cuts->get(binPt, "pT K")) {
913+
return false;
914+
}
915+
916+
// J/Psi pt
917+
if (ptJpsi < cuts->get(binPt, "pT J/Psi")) {
918+
return false;
919+
}
920+
921+
// J/Psi mass
922+
if (std::abs(candJpsi.m() - o2::constants::physics::MassJPsi) < cuts->get(binPt, "DeltaM J/Psi")) {
923+
return false;
924+
}
925+
926+
// d0(J/Psi)xd0(K)
927+
if (candBp.impactParameterProduct() > cuts->get(binPt, "B Imp. Par. Product")) {
928+
return false;
929+
}
930+
931+
// B+ Decay length
932+
if (candBp.decayLength() < cuts->get(binPt, "B decLen")) {
933+
return false;
934+
}
935+
936+
// B+ Decay length XY
937+
if (candBp.decayLengthXY() < cuts->get(binPt, "B decLenXY")) {
938+
return false;
939+
}
940+
941+
// B+ CPA cut
942+
if (candBp.cpa() < cuts->get(binPt, "CPA")) {
943+
return false;
944+
}
945+
946+
// B+ CPAXY cut
947+
if (candBp.cpaXY() < cuts->get(binPt, "CPAXY")) {
948+
return false;
949+
}
950+
951+
// d0 of K
952+
if (std::abs(candBp.impactParameter1()) < cuts->get(binPt, "d0 K")) {
953+
return false;
954+
}
955+
956+
// d0 of J/Psi
957+
if (std::abs(candBp.impactParameter0()) < cuts->get(binPt, "d0 J/Psi")) {
958+
return false;
959+
}
960+
961+
// B pseudoproper decay length
962+
if (pseudoPropDecLen < cuts->get(binPt, "B pseudoprop. decLen")) {
963+
return false;
964+
}
965+
966+
return true;
967+
}
968+
969+
/// Apply PID selection
970+
/// \param pidTrackKa PID status of trackKa (prong1 of B+ candidate)
971+
/// \param acceptPIDNotApplicable switch to accept Status::NotApplicable
972+
/// \return true if prong1 of B+ candidate passes all selections
973+
bool selectionBplusToJpsiKPid(const int pidTrackKa, const bool acceptPIDNotApplicable)
974+
{
975+
if (!acceptPIDNotApplicable && pidTrackKa != TrackSelectorPID::Accepted) {
976+
return false;
977+
}
978+
if (acceptPIDNotApplicable && pidTrackKa == TrackSelectorPID::Rejected) {
979+
return false;
980+
}
981+
982+
return true;
983+
}
984+
876985
/// Apply topological cuts as defined in SelectorCuts.h
877986
/// \param candBs Bs candidate
878987
/// \param cuts Bs candidate selections
@@ -947,8 +1056,7 @@ class HfHelper
9471056
/// \param pidTrackPi PID status of trackPi (prong1 of Bs candidate)
9481057
/// \param acceptPIDNotApplicable switch to accept Status::NotApplicable
9491058
/// \return true if prong1 of Bs candidate passes all selections
950-
template <typename T1 = int, typename T2 = bool>
951-
bool selectionBsToDsPiPid(const T1& pidTrackPi, const T2& acceptPIDNotApplicable)
1059+
bool selectionBsToDsPiPid(const int pidTrackPi, const bool acceptPIDNotApplicable)
9521060
{
9531061
if (!acceptPIDNotApplicable && pidTrackPi != TrackSelectorPID::Accepted) {
9541062
return false;
@@ -960,6 +1068,115 @@ class HfHelper
9601068
return true;
9611069
}
9621070

1071+
// Apply topological cuts as defined in SelectorCuts.h
1072+
/// \param candBs Bs candidate
1073+
/// \param candKa0 kaon candidate 0 (phi daughter)
1074+
/// \param candKa1 kaon candidate 1 (phi daughter)
1075+
/// \param cuts Bs candidate selection per pT bin
1076+
/// \param binsPt pT bin limits
1077+
/// \return true if candidate passes all selections
1078+
template <typename T1, typename T2, typename T3, typename T4, typename T5>
1079+
bool selectionBsToJpsiPhiTopol(const T1& candBs, const T2& candKa0, const T3& candKa1, const T4& cuts, const T5& binsPt)
1080+
{
1081+
auto ptCandBs = candBs.pt();
1082+
auto mCandBs = invMassBsToJpsiPhi(candBs);
1083+
std::array<float, 3> pVecKa0 = candKa0.pVector();
1084+
std::array<float, 3> pVecKa1 = candKa1.pVector();
1085+
auto mCandPhi = RecoDecay::m(std::array{pVecKa0, pVecKa1}, std::array{o2::constants::physics::MassKPlus, o2::constants::physics::MassKPlus});
1086+
auto ptJpsi = RecoDecay::pt(candBs.pxProng0(), candBs.pyProng0());
1087+
auto candJpsi = candBs.jpsi();
1088+
float pseudoPropDecLen = candBs.decayLengthXY() * mCandBs / ptCandBs;
1089+
1090+
int binPt = o2::analysis::findBin(binsPt, ptCandBs);
1091+
if (binPt == -1) {
1092+
return false;
1093+
}
1094+
1095+
// Bs mass cut
1096+
if (std::abs(mCandBs - o2::constants::physics::MassBPlus) > cuts->get(binPt, "m")) {
1097+
return false;
1098+
}
1099+
1100+
// kaon pt
1101+
if (candKa0.pt() < cuts->get(binPt, "pT K") &&
1102+
candKa1.pt() < cuts->get(binPt, "pT K")) {
1103+
return false;
1104+
}
1105+
1106+
// J/Psi pt
1107+
if (ptJpsi < cuts->get(binPt, "pT J/Psi")) {
1108+
return false;
1109+
}
1110+
1111+
// phi mass
1112+
if (std::abs(mCandPhi - o2::constants::physics::MassPhi) < cuts->get(binPt, "DeltaM phi")) {
1113+
return false;
1114+
}
1115+
1116+
// J/Psi mass
1117+
if (std::abs(candJpsi.m() - o2::constants::physics::MassJPsi) < cuts->get(binPt, "DeltaM J/Psi")) {
1118+
return false;
1119+
}
1120+
1121+
// d0(J/Psi)xd0(phi)
1122+
if (candBs.impactParameterProduct() > cuts->get(binPt, "B Imp. Par. Product")) {
1123+
return false;
1124+
}
1125+
1126+
// Bs Decay length
1127+
if (candBs.decayLength() < cuts->get(binPt, "B decLen")) {
1128+
return false;
1129+
}
1130+
1131+
// Bs Decay length XY
1132+
if (candBs.decayLengthXY() < cuts->get(binPt, "B decLenXY")) {
1133+
return false;
1134+
}
1135+
1136+
// Bs CPA cut
1137+
if (candBs.cpa() < cuts->get(binPt, "CPA")) {
1138+
return false;
1139+
}
1140+
1141+
// Bs CPAXY cut
1142+
if (candBs.cpaXY() < cuts->get(binPt, "CPAXY")) {
1143+
return false;
1144+
}
1145+
1146+
// d0 of phi
1147+
if (std::abs(candBs.impactParameter1()) < cuts->get(binPt, "d0 phi")) {
1148+
return false;
1149+
}
1150+
1151+
// d0 of J/Psi
1152+
if (std::abs(candBs.impactParameter0()) < cuts->get(binPt, "d0 J/Psi")) {
1153+
return false;
1154+
}
1155+
1156+
// B pseudoproper decay length
1157+
if (pseudoPropDecLen < cuts->get(binPt, "B pseudoprop. decLen")) {
1158+
return false;
1159+
}
1160+
1161+
return true;
1162+
}
1163+
1164+
/// Apply PID selection
1165+
/// \param pidTrackKa PID status of trackKa (prong1 of B+ candidate)
1166+
/// \param acceptPIDNotApplicable switch to accept Status::NotApplicable
1167+
/// \return true if prong1 of B+ candidate passes all selections
1168+
bool selectionBsToJpsiPhiPid(const int pidTrackKa, const bool acceptPIDNotApplicable)
1169+
{
1170+
if (!acceptPIDNotApplicable && pidTrackKa != TrackSelectorPID::Accepted) {
1171+
return false;
1172+
}
1173+
if (acceptPIDNotApplicable && pidTrackKa == TrackSelectorPID::Rejected) {
1174+
return false;
1175+
}
1176+
1177+
return true;
1178+
}
1179+
9631180
/// Apply topological cuts as defined in SelectorCuts.h
9641181
/// \param candLb Lb candidate
9651182
/// \param cuts Lb candidate selection per pT bin"
@@ -1028,8 +1245,7 @@ class HfHelper
10281245
/// \param pidTrackPi PID status of trackPi (prong1 of Lb candidate)
10291246
/// \param acceptPIDNotApplicable switch to accept Status::NotApplicable
10301247
/// \return true if prong1 of Lb candidate passes all selections
1031-
template <typename T1 = int, typename T2 = bool>
1032-
bool selectionLbToLcPiPid(const T1& pidTrackPi, const T2& acceptPIDNotApplicable)
1248+
bool selectionLbToLcPiPid(const int pidTrackPi, const bool acceptPIDNotApplicable)
10331249
{
10341250
if (!acceptPIDNotApplicable && pidTrackPi != TrackSelectorPID::Accepted) {
10351251
return false;

0 commit comments

Comments
 (0)