Skip to content

Commit 4ac7d66

Browse files
authored
added SigmaC-proton trigger
Added support for SigmaC particle selection in the HfFilterHelper class.
1 parent 21fcb3a commit 4ac7d66

File tree

1 file changed

+164
-3
lines changed

1 file changed

+164
-3
lines changed

EventFiltering/PWGHF/HFFilterHelpers.h

Lines changed: 164 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@
2828
//
2929
#include "Common/Core/RecoDecay.h"
3030
#include "Common/Core/trackUtilities.h"
31+
#include "Common/DataModel/PIDResponseTOF.h"
32+
#include "Common/DataModel/PIDResponseTPC.h"
33+
#include "ReconstructionDataFormats/PID.h"
3134

3235
#include <CCDB/BasicCCDBManager.h>
3336
#include <CCDB/CcdbApi.h>
@@ -97,6 +100,7 @@ enum HfTriggers {
97100
kBtoJPsiPhi,
98101
kBtoJPsiPrKa,
99102
kBtoJPsiPi,
103+
kSigmaCP,
100104
kNtriggersHF
101105
};
102106

@@ -245,7 +249,7 @@ static const int nTotBeautyParts = static_cast<int>(kNBeautyParticles) + static_
245249
static const std::array<std::string, nTotBeautyParts> beautyParticleNames{"Bplus", "B0toDStar", "Bc", "B0", "Bs", "Lb", "Xib", "BplusToJPsi", "B0ToJPsi", "BsToJPsi", "LbToJPsi", "BcToJPsi"};
246250
static const std::array<int, kNCharmParticles> pdgCodesCharm{421, 411, 431, 4122, 4232};
247251
static const std::array<std::string, 2> eventTitles = {"all", "rejected"};
248-
static const std::vector<std::string> hfTriggerNames{filtering::HfHighPt2P::columnLabel(), filtering::HfHighPt3P::columnLabel(), filtering::HfBeauty3P::columnLabel(), filtering::HfBeauty4P::columnLabel(), filtering::HfFemto2P::columnLabel(), filtering::HfFemto3P::columnLabel(), filtering::HfDoubleCharm2P::columnLabel(), filtering::HfDoubleCharm3P::columnLabel(), filtering::HfDoubleCharmMix::columnLabel(), filtering::HfV0Charm2P::columnLabel(), filtering::HfV0Charm3P::columnLabel(), filtering::HfCharmBarToXiBach::columnLabel(), filtering::HfSigmaCPPK::columnLabel(), filtering::HfSigmaC0K0::columnLabel(), filtering::HfPhotonCharm2P::columnLabel(), filtering::HfPhotonCharm3P::columnLabel(), filtering::HfSingleCharm2P::columnLabel(), filtering::HfSingleCharm3P::columnLabel(), filtering::HfSingleNonPromptCharm2P::columnLabel(), filtering::HfSingleNonPromptCharm3P::columnLabel(), filtering::HfCharmBarToXi2Bach::columnLabel(), filtering::HfPrCharm2P::columnLabel(), filtering::HfBtoJPsiKa::columnLabel(), filtering::HfBtoJPsiKstar::columnLabel(), filtering::HfBtoJPsiPhi::columnLabel(), filtering::HfBtoJPsiPrKa::columnLabel(), filtering::HfBtoJPsiPi::columnLabel()};
252+
static const std::vector<std::string> hfTriggerNames{filtering::HfHighPt2P::columnLabel(), filtering::HfHighPt3P::columnLabel(), filtering::HfBeauty3P::columnLabel(), filtering::HfBeauty4P::columnLabel(), filtering::HfFemto2P::columnLabel(), filtering::HfFemto3P::columnLabel(), filtering::HfDoubleCharm2P::columnLabel(), filtering::HfDoubleCharm3P::columnLabel(), filtering::HfDoubleCharmMix::columnLabel(), filtering::HfV0Charm2P::columnLabel(), filtering::HfV0Charm3P::columnLabel(), filtering::HfCharmBarToXiBach::columnLabel(), filtering::HfSigmaCPPK::columnLabel(), filtering::HfSigmaC0K0::columnLabel(), filtering::HfPhotonCharm2P::columnLabel(), filtering::HfPhotonCharm3P::columnLabel(), filtering::HfSingleCharm2P::columnLabel(), filtering::HfSingleCharm3P::columnLabel(), filtering::HfSingleNonPromptCharm2P::columnLabel(), filtering::HfSingleNonPromptCharm3P::columnLabel(), filtering::HfCharmBarToXi2Bach::columnLabel(), filtering::HfPrCharm2P::columnLabel(), filtering::HfBtoJPsiKa::columnLabel(), filtering::HfBtoJPsiKstar::columnLabel(), filtering::HfBtoJPsiPhi::columnLabel(), filtering::HfBtoJPsiPrKa::columnLabel(), filtering::HfBtoJPsiPi::columnLabel(), filtering::HfSigmaCP::columnLabel()};
249253

250254
static const std::array<std::string, kNV0> v0Labels{"#gamma", "K_{S}^{0}", "#Lambda", "#bar{#Lambda}"};
251255
static const std::array<std::string, kNV0> v0Names{"Photon", "K0S", "Lambda", "AntiLambda"};
@@ -293,7 +297,7 @@ static const o2::framework::AxisSpec alphaAxis{100, -1.f, 1.f};
293297
static const o2::framework::AxisSpec qtAxis{100, 0.f, 0.25f};
294298
static const o2::framework::AxisSpec bdtAxis{100, 0.f, 1.f};
295299
static const o2::framework::AxisSpec phiAxis{36, 0., o2::constants::math::TwoPI};
296-
static const std::array<o2::framework::AxisSpec, kNCharmParticles + 23> massAxisC = {o2::framework::AxisSpec{250, 1.65f, 2.15f}, o2::framework::AxisSpec{250, 1.65f, 2.15f}, o2::framework::AxisSpec{250, 1.75f, 2.25f}, o2::framework::AxisSpec{250, 2.05f, 2.55f}, o2::framework::AxisSpec{250, 2.25f, 2.75f}, o2::framework::AxisSpec{200, 0.139f, 0.159f}, o2::framework::AxisSpec{250, 0.f, 0.25f}, o2::framework::AxisSpec{250, 0.f, 0.25f}, o2::framework::AxisSpec{200, 0.48f, 0.88f}, o2::framework::AxisSpec{200, 0.48f, 0.88f}, o2::framework::AxisSpec{200, 1.1f, 1.4f}, o2::framework::AxisSpec{200, 1.1f, 1.4f}, o2::framework::AxisSpec{200, 1.1f, 1.4f}, o2::framework::AxisSpec{200, 1.1f, 1.4f}, o2::framework::AxisSpec{170, 0.13f, 0.3f}, o2::framework::AxisSpec{170, 0.13f, 0.3f}, o2::framework::AxisSpec{200, 0.4f, 0.8f}, o2::framework::AxisSpec{200, 0.4f, 0.8f}, o2::framework::AxisSpec{200, 0.4f, 0.8f}, o2::framework::AxisSpec{200, 0.4f, 0.8f}, o2::framework::AxisSpec{350, 2.3f, 3.0f}, o2::framework::AxisSpec{350, 2.3f, 3.0f}, o2::framework::AxisSpec{350, 2.3f, 3.0f}, o2::framework::AxisSpec{240, 2.4f, 3.6f}, o2::framework::AxisSpec{300, 0.7f, 1.3f}, o2::framework::AxisSpec{300, 0.7f, 1.3f}, o2::framework::AxisSpec{300, 0.7f, 1.3f}, o2::framework::AxisSpec{300, 0.7f, 1.3f}};
300+
static const std::array<o2::framework::AxisSpec, kNCharmParticles + 24> massAxisC = {o2::framework::AxisSpec{250, 1.65f, 2.15f}, o2::framework::AxisSpec{250, 1.65f, 2.15f}, o2::framework::AxisSpec{250, 1.75f, 2.25f}, o2::framework::AxisSpec{250, 2.05f, 2.55f}, o2::framework::AxisSpec{250, 2.25f, 2.75f}, o2::framework::AxisSpec{200, 0.139f, 0.159f}, o2::framework::AxisSpec{250, 0.f, 0.25f}, o2::framework::AxisSpec{250, 0.f, 0.25f}, o2::framework::AxisSpec{200, 0.48f, 0.88f}, o2::framework::AxisSpec{200, 0.48f, 0.88f}, o2::framework::AxisSpec{200, 1.1f, 1.4f}, o2::framework::AxisSpec{200, 1.1f, 1.4f}, o2::framework::AxisSpec{200, 1.1f, 1.4f}, o2::framework::AxisSpec{200, 1.1f, 1.4f}, o2::framework::AxisSpec{170, 0.13f, 0.3f}, o2::framework::AxisSpec{170, 0.13f, 0.3f}, o2::framework::AxisSpec{200, 0.4f, 0.8f}, o2::framework::AxisSpec{200, 0.4f, 0.8f}, o2::framework::AxisSpec{200, 0.4f, 0.8f}, o2::framework::AxisSpec{200, 0.4f, 0.8f}, o2::framework::AxisSpec{350, 2.3f, 3.0f}, o2::framework::AxisSpec{350, 2.3f, 3.0f}, o2::framework::AxisSpec{350, 2.3f, 3.0f}, o2::framework::AxisSpec{240, 2.4f, 3.6f}, o2::framework::AxisSpec{300, 0.7f, 1.3f}, o2::framework::AxisSpec{300, 0.7f, 1.3f}, o2::framework::AxisSpec{300, 0.7f, 1.3f}, o2::framework::AxisSpec{300, 0.7f, 1.3f}, o2::framework::AxisSpec{300, 0.14f, 0.26f}};
297301
static const std::array<o2::framework::AxisSpec, nTotBeautyParts> massAxisB = {o2::framework::AxisSpec{500, 4.2f, 6.2f}, o2::framework::AxisSpec{500, 4.2f, 6.2f}, o2::framework::AxisSpec{500, 5.4f, 7.4f}, o2::framework::AxisSpec{500, 4.2f, 6.2f}, o2::framework::AxisSpec{500, 4.4f, 6.4f}, o2::framework::AxisSpec{400, 5.0f, 6.6f}, o2::framework::AxisSpec{500, 4.2f, 6.2f}, o2::framework::AxisSpec{500, 4.2f, 6.2f}, o2::framework::AxisSpec{500, 4.2f, 6.2f}, o2::framework::AxisSpec{500, 4.2f, 6.2f}, o2::framework::AxisSpec{400, 5.0f, 6.6f}, o2::framework::AxisSpec{240, 5.8f, 7.0f}};
298302

299303
// default values for configurables
@@ -625,6 +629,8 @@ class HfFilterHelper
625629
int16_t isSelectedTrackForSoftPionOrBeauty(const T& track, const T1& trackPar, const T2& dca);
626630
template <typename T1, typename T2, typename H2>
627631
bool isSelectedTrack4Femto(const T1& track, const T2& trackPar, const int& activateQA, H2 hTPCPID, H2 hTOFPID, const int& trackSpecies);
632+
template <typename Atrack, typename SpeciesContainer, typename T1, typename T2>
633+
bool isSelectedTrack4Corr(Atrack const& track, SpeciesContainer const mPIDspecies, T1 const maxTPC, T2 const maxTOF, float minPt = 0.39, float maxPt = 4.6, float ptThreshold = 1.0, bool tofForced = false);
628634
template <typename T>
629635
int8_t isDzeroPreselected(const T& trackPos, const T& trackNeg);
630636
template <typename T>
@@ -644,6 +650,8 @@ class HfFilterHelper
644650
template <int charge, typename T, typename H2>
645651
int8_t isSelectedSigmaCInDeltaMassRange(const T& pTrackSameChargeFirst, const T& pTrackSameChargeSecond, const T& pTrackOppositeCharge, const T& pTrackSoftPi, const float ptSigmaC, const int8_t isSelectedLc, H2 hMassVsPt, const int& activateQA);
646652
template <typename T, typename H2>
653+
bool selectionSigmaCForScPCorr(const T& pTrackSameChargeFirst, const T& pTrackSameChargeSecond, const T& pTrackOppositeCharge, const T& pTrackSoftPi, const float ptSigmaC, const int8_t isSelectedLc, H2 hMassVsPt, const int& activateQA, float mDeltaMassMinSigmaC = 0.155, float mDeltaMassMaxSigmaC = 0.2, float mPtMinSigmaC = 4.99, float mPtMaxSigmaC = 12.0);
654+
template <typename T, typename H2>
647655
int8_t isSelectedXicInMassRange(const T& pTrackSameChargeFirst, const T& pTrackSameChargeSecond, const T& pTrackOppositeCharge, const float& ptXic, const int8_t isSelected, const int& activateQA, H2 hMassVsPt);
648656
template <typename V0, typename H2>
649657
int8_t isSelectedV0(const V0& v0, const int& activateQA, H2 hV0Selected, std::array<H2, 4>& hArmPod);
@@ -867,7 +875,7 @@ inline int16_t HfFilterHelper::isSelectedTrackForSoftPionOrBeauty(const T& track
867875
return kRejected;
868876
}
869877

870-
if constexpr (whichTrigger == kSigmaCPPK || whichTrigger == kSigmaC0K0) {
878+
if constexpr (whichTrigger == kSigmaCPPK || whichTrigger == kSigmaC0K0 || whichTrigger == kSigmaCP) {
871879

872880
// SigmaC0,++ soft pion pt cut
873881
if (pT < mPtMinSoftPionForSigmaC || pT > mPtMaxSoftPionForSigmaC) {
@@ -922,6 +930,113 @@ inline int16_t HfFilterHelper::isSelectedTrackForSoftPionOrBeauty(const T& track
922930
return retValue;
923931
}
924932

933+
/// Basic selection of proton or deuteron candidates
934+
/// \param track is a track
935+
/// \param mPIDspecies is a vector of different particle species
936+
/// \param activateQA flag to activate the filling of QA histos
937+
/// \param maxTPC is a vector of max TPCnSigma for different particle species
938+
/// \param maxTOF is a vector of max TOFnSigma for different particle species
939+
/// \param hProtonTPCPID histo with NsigmaTPC vs. p
940+
/// \param hProtonTOFPID histo with NsigmaTOF vs. p
941+
/// \return true if track passes all cuts
942+
template <typename Atrack, typename SpeciesContainer, typename T1, typename T2>
943+
inline bool HfFilterHelper::isSelectedTrack4Corr(Atrack const& track, SpeciesContainer const mPIDspecies,
944+
T1 const maxTPC, T2 const maxTOF, float minPt, float maxPt, float ptThreshold, bool tofForced)
945+
{
946+
// Ensure size consistency
947+
if (mPIDspecies.value.size() != maxTPC.value.size() || mPIDspecies.value.size() != maxTOF.value.size()) {
948+
LOGF(error, "Size of particle species and corresponding nSigma selection arrays should be the same");
949+
return false; // Early exit on error
950+
}
951+
952+
if (!track.isGlobalTrackWoDCA()) {
953+
return false;
954+
}
955+
956+
if (track.pt() < minPt || track.pt() > maxPt){
957+
return false;
958+
}
959+
960+
for (size_t speciesIndex = 0; speciesIndex < mPIDspecies.value.size(); ++speciesIndex) {
961+
float nSigmaTPC;
962+
auto const& pid = mPIDspecies->at(speciesIndex);
963+
964+
nSigmaTPC = o2::aod::pidutils::tpcNSigma(pid, track);
965+
966+
if (track.pt() > ptThreshold && tofForced && !track.hasTOF())
967+
return false;
968+
969+
int parSpecies = -1;
970+
float tpcNCls = track.tpcNClsFound();
971+
float tpcPin = track.tpcInnerParam();
972+
float eta = track.eta();
973+
974+
if (pid == o2::track::PID::Proton) {
975+
parSpecies = kPr;
976+
} else if (pid == o2::track::PID::Kaon) {
977+
parSpecies = kKa;
978+
} else if (pid == o2::track::PID::Pion) {
979+
parSpecies = kPi;
980+
} else {
981+
LOGF(fatal, "particle species is not defined in isSelectedTrack4Corr");
982+
}
983+
984+
// 2. Apply nSigmaTPC using selected calibration
985+
if (mTpcPidCalibrationOption == 1) {
986+
// Option 1: post-calibration → no sign dependence
987+
nSigmaTPC = getTPCPostCalib(tpcPin, tpcNCls, eta, nSigmaTPC, parSpecies);
988+
989+
}
990+
if (mTpcPidCalibrationOption == 2) {
991+
float dEdx = track.tpcSignal();
992+
// Option 2: spline calibration → charge-dependent
993+
if (track.sign() > 0) {
994+
// Positive track
995+
nSigmaTPC = getTPCSplineCalib(tpcPin, dEdx, parSpecies);
996+
} else {
997+
// Negative track
998+
if (pid == o2::track::PID::Proton) {
999+
parSpecies = kAntiPr;
1000+
} else if (pid == o2::track::PID::Kaon) {
1001+
parSpecies = kAntiKa;
1002+
} else if (pid == o2::track::PID::Pion) {
1003+
parSpecies = kAntiPi;
1004+
} else {
1005+
LOGF(fatal, "particle species is not defined in isSelectedTrack4Corr");
1006+
}
1007+
nSigmaTPC = getTPCSplineCalib(tpcPin, dEdx, parSpecies);
1008+
}
1009+
}
1010+
1011+
if (speciesIndex == 0) { // First species logic
1012+
1013+
if (std::abs(nSigmaTPC) > maxTPC->at(speciesIndex)) {
1014+
return false; // TPC check failed
1015+
}
1016+
if (track.hasTOF()) {
1017+
auto nSigmaTOF = o2::aod::pidutils::tofNSigma(pid, track);
1018+
if (std::abs(nSigmaTOF) > maxTOF->at(speciesIndex)) {
1019+
return false; // TOF check failed
1020+
}
1021+
}
1022+
} else { // Other species logic
1023+
if (std::abs(nSigmaTPC) < maxTPC->at(speciesIndex)) { // Check TPC nSigma first
1024+
if (track.hasTOF()) {
1025+
auto nSigmaTOF = o2::aod::pidutils::tofNSigma(pid, track);
1026+
if (std::abs(nSigmaTOF) < maxTOF->at(speciesIndex)) {
1027+
return false; // Reject if both TPC and TOF are within thresholds
1028+
}
1029+
} else {
1030+
return false; // Reject if only TPC is within threshold and TOF is unavailable
1031+
}
1032+
}
1033+
}
1034+
}
1035+
return true; // Passed all checks
1036+
}
1037+
1038+
1039+
9251040
/// Basic selection of proton or deuteron candidates
9261041
/// \param track is a track
9271042
/// \param trackPar is a track parameter
@@ -1312,6 +1427,52 @@ inline int8_t HfFilterHelper::isSelectedLcInMassRange(const T& pTrackSameChargeF
13121427
return retValue;
13131428
}
13141429

1430+
/// Delta mass selection on SigmaC candidates for correlation
1431+
template <typename T, typename H2>
1432+
inline bool HfFilterHelper::selectionSigmaCForScPCorr(const T& pTrackSameChargeFirst, const T& pTrackSameChargeSecond, const T& pTrackOppositeCharge, const T& pTrackSoftPi, const float ptSigmaC, const int8_t isSelectedLc, H2 hMassVsPt, const int& activateQA, float mDeltaMassMinSigmaC, float mDeltaMassMaxSigmaC, float mPtMinSigmaC, float mPtMaxSigmaC)
1433+
{
1434+
if (ptSigmaC < mPtMinSigmaC || ptSigmaC > mPtMaxSigmaC){
1435+
return false;
1436+
}
1437+
bool isSigmaCSelected{false};
1438+
if (TESTBIT(isSelectedLc, 0)) {
1439+
/// Lc->pKpi case
1440+
auto invMassLcToPKPi = RecoDecay::m(std::array{pTrackSameChargeFirst, pTrackOppositeCharge, pTrackSameChargeSecond}, std::array{massProton, massKa, massPi});
1441+
std::array<float, 4> massDausSigmaCToLcPKPi{massProton, massKa, massPi, massPi};
1442+
float invMassSigmaCToLcPKPi = RecoDecay::m(std::array{pTrackSameChargeFirst, pTrackOppositeCharge, pTrackSameChargeSecond, pTrackSoftPi}, massDausSigmaCToLcPKPi);
1443+
float deltaMassPKPi = invMassSigmaCToLcPKPi - invMassLcToPKPi;
1444+
isSigmaCSelected = (mDeltaMassMinSigmaC < deltaMassPKPi && deltaMassPKPi < mDeltaMassMaxSigmaC);
1445+
if(isSigmaCSelected){
1446+
if (activateQA){
1447+
hMassVsPt->Fill(ptSigmaC, deltaMassPKPi);
1448+
}
1449+
return true;
1450+
}
1451+
1452+
}
1453+
if (TESTBIT(isSelectedLc, 1)) {
1454+
/// Lc->piKp case
1455+
auto invMassLcToPiKP = RecoDecay::m(std::array{pTrackSameChargeFirst, pTrackOppositeCharge, pTrackSameChargeSecond}, std::array{massPi, massKa, massProton});
1456+
std::array<float, 4> massDausSigmaCToLcPiKP{massPi, massKa, massProton, massPi};
1457+
float invMassSigmaCToLcPiKP = RecoDecay::m(std::array{pTrackSameChargeFirst, pTrackOppositeCharge, pTrackSameChargeSecond, pTrackSoftPi}, massDausSigmaCToLcPiKP);
1458+
float deltaMassPiKP = invMassSigmaCToLcPiKP - invMassLcToPiKP;
1459+
1460+
isSigmaCSelected = (mDeltaMassMinSigmaC < deltaMassPiKP && deltaMassPiKP < mDeltaMassMaxSigmaC);
1461+
if(isSigmaCSelected){
1462+
if (activateQA){
1463+
hMassVsPt->Fill(ptSigmaC, deltaMassPiKP);
1464+
}
1465+
return true;
1466+
}
1467+
1468+
}
1469+
1470+
return isSigmaCSelected;
1471+
/// TODO: add QA plot
1472+
}
1473+
1474+
1475+
13151476
/// Delta mass selection on SigmaC candidates
13161477
template <int charge, typename T, typename H2>
13171478
inline int8_t HfFilterHelper::isSelectedSigmaCInDeltaMassRange(const T& pTrackSameChargeFirst, const T& pTrackSameChargeSecond, const T& pTrackOppositeCharge, const T& pTrackSoftPi, const float ptSigmaC, const int8_t isSelectedLc, H2 hMassVsPt, const int& activateQA)

0 commit comments

Comments
 (0)