Skip to content

Commit 51f9794

Browse files
nzardoshalibuild
andauthored
[PWGHF,PWGJE] Update B+ selector task to be similar to B+ reduced selector task and use machine learning (AliceO2Group#8858)
Co-authored-by: ALICE Action Bot <[email protected]>
1 parent 1bc14fd commit 51f9794

15 files changed

+448
-150
lines changed

PWGHF/Core/HfHelper.h

+32-7
Original file line numberDiff line numberDiff line change
@@ -947,34 +947,59 @@ class HfHelper
947947
}
948948

949949
/// Apply selection on ML scores for charm-hadron daughter in b-hadron decays (common for all the beauty channels)
950-
/// \param candB b-hadron candidates
951950
/// \param cuts ML score selection per bin of charm-hadron pT
952951
/// \param binsPtC pT bin limits of charm hadron
952+
/// \param mlScores vector with ml scores of charm hadron (position 0:bkg 1:prompt 2:nonprompt)
953953
/// \return true if b-hadron candidate passes all selections
954-
template <typename T1, typename T2, typename T3>
955-
bool selectionDmesMlScoresForB(const T1& candB, const T2& cuts, const T3& binsPtC)
954+
template <typename T1, typename T2>
955+
bool applySelectionDmesMlScoresForB(const T1& cuts, const T2& binsPtC, float ptC, std::vector<float> mlScores)
956956
{
957-
auto ptC = RecoDecay::pt(candB.pxProng0(), candB.pyProng0()); // the first daughter is the charm hadron
958957
int pTBin = o2::analysis::findBin(binsPtC, ptC);
959958
if (pTBin == -1) {
960959
return false;
961960
}
962961

963-
if (candB.prong0MlScoreBkg() > cuts->get(pTBin, "ML score charm bkg")) {
962+
if (mlScores[0] > cuts->get(pTBin, "ML score charm bkg")) {
964963
return false;
965964
}
966965

967-
if (candB.prong0MlScorePrompt() > cuts->get(pTBin, "ML score charm prompt")) { // we want non-prompt for beauty
966+
if (mlScores[1] > cuts->get(pTBin, "ML score charm prompt")) { // we want non-prompt for beauty
968967
return false;
969968
}
970969

971-
if (candB.prong0MlScoreNonprompt() < cuts->get(pTBin, "ML score charm nonprompt")) { // we want non-prompt for beauty
970+
if (mlScores[2] < cuts->get(pTBin, "ML score charm nonprompt")) { // we want non-prompt for beauty
972971
return false;
973972
}
974973

975974
return true;
976975
}
977976

977+
/// Apply selection on ML scores for charm-hadron daughter in b-hadron decays (could be common for all the beauty channels)
978+
/// \param candB b-hadron candidates
979+
/// \param cuts ML score selection per bin of charm-hadron pT
980+
/// \param binsPtC pT bin limits of charm hadron
981+
/// \return true if b-hadron candidate passes all selections
982+
template <typename T1, typename T2, typename T3>
983+
bool selectionDmesMlScoresForB(const T1& candD, const T2& cuts, const T3& binsPtC, const std::vector<float>& mlScores)
984+
{
985+
return applySelectionDmesMlScoresForB(cuts, binsPtC, candD.pt(), mlScores);
986+
}
987+
988+
/// Apply selection on ML scores for charm-hadron daughter in b-hadron decays in reduced format (common for all the beauty channels)
989+
/// \param candB b-hadron candidates
990+
/// \param cuts ML score selection per bin of charm-hadron pT
991+
/// \param binsPtC pT bin limits of charm hadron
992+
/// \return true if b-hadron candidate passes all selections
993+
template <typename T1, typename T2, typename T3>
994+
bool selectionDmesMlScoresForBReduced(const T1& candB, const T2& cuts, const T3& binsPtC)
995+
{
996+
std::vector<float> mlScores;
997+
mlScores.push_back(candB.prong0MlScoreBkg());
998+
mlScores.push_back(candB.prong0MlScorePrompt());
999+
mlScores.push_back(candB.prong0MlScoreNonprompt()); // we want non-prompt for beauty
1000+
return applySelectionDmesMlScoresForB(cuts, binsPtC, RecoDecay::pt(candB.pxProng0(), candB.pyProng0()), mlScores);
1001+
}
1002+
9781003
private:
9791004
};
9801005

PWGHF/Core/HfMlResponseBplusToD0Pi.h

+27-14
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,9 @@
2626
// Fill the map of available input features
2727
// the key is the feature's name (std::string)
2828
// the value is the corresponding value in EnumInputFeatures
29-
#define FILL_MAP_BPLUS(FEATURE) \
30-
{ \
31-
#FEATURE, static_cast < uint8_t>(InputFeaturesBplusToD0Pi::FEATURE) \
29+
#define FILL_MAP_BPLUS(FEATURE) \
30+
{ \
31+
#FEATURE, static_cast<uint8_t>(InputFeaturesBplusToD0Pi::FEATURE) \
3232
}
3333

3434
// Check if the index of mCachedIndices (index associated to a FEATURE)
@@ -59,6 +59,17 @@
5959
break; \
6060
}
6161

62+
// where OBJECT is named candidateD , FEATURE = GETTER and INDEX is the index of the vector
63+
#define CHECK_AND_FILL_VEC_D0_INDEX(FEATURE, GETTER1, GETTER2, INDEX) \
64+
case static_cast<uint8_t>(InputFeaturesBplusToD0Pi::FEATURE): { \
65+
if (pdgCode == o2::constants::physics::kD0) { \
66+
inputFeatures.emplace_back((candidateD0.GETTER1())[INDEX]); \
67+
} else { \
68+
inputFeatures.emplace_back((candidateD0.GETTER2())[INDEX]); \
69+
} \
70+
break; \
71+
}
72+
6273
namespace o2::analysis
6374
{
6475

@@ -76,9 +87,9 @@ enum class InputFeaturesBplusToD0Pi : uint8_t {
7687
cpa,
7788
cpaXY,
7889
maxNormalisedDeltaIP,
79-
prong0MlScoreBkg,
80-
prong0MlScorePrompt,
81-
prong0MlScoreNonprompt,
90+
prong0MlProbBkg,
91+
prong0MlProbPrompt,
92+
prong0MlProbNonPrompt,
8293
tpcNSigmaPi1,
8394
tofNSigmaPi1,
8495
tpcTofNSigmaPi1
@@ -97,9 +108,11 @@ class HfMlResponseBplusToD0Pi : public HfMlResponse<TypeOutputScore>
97108
/// \param candidate is the B+ candidate
98109
/// \param prong1 is the candidate's prong1
99110
/// \return inputFeatures vector
100-
template <bool withDmesMl, typename T1, typename T2>
111+
template <bool withDmesMl, typename T1, typename T2, typename T3>
101112
std::vector<float> getInputFeatures(T1 const& candidate,
102-
T2 const& prong1)
113+
T2 const& candidateD0,
114+
int const& pdgCode,
115+
T3 const& prong1)
103116
{
104117
std::vector<float> inputFeatures;
105118

@@ -119,9 +132,9 @@ class HfMlResponseBplusToD0Pi : public HfMlResponse<TypeOutputScore>
119132
CHECK_AND_FILL_VEC_BPLUS(cpa);
120133
CHECK_AND_FILL_VEC_BPLUS(cpaXY);
121134
CHECK_AND_FILL_VEC_BPLUS(maxNormalisedDeltaIP);
122-
CHECK_AND_FILL_VEC_BPLUS(prong0MlScoreBkg);
123-
CHECK_AND_FILL_VEC_BPLUS(prong0MlScorePrompt);
124-
CHECK_AND_FILL_VEC_BPLUS(prong0MlScoreNonprompt);
135+
CHECK_AND_FILL_VEC_D0_INDEX(prong0MlProbBkg, mlProbD0, mlProbD0bar, 0);
136+
CHECK_AND_FILL_VEC_D0_INDEX(prong0MlProbPrompt, mlProbD0, mlProbD0bar, 1);
137+
CHECK_AND_FILL_VEC_D0_INDEX(prong0MlProbNonPrompt, mlProbD0, mlProbD0bar, 2);
125138
// TPC PID variable
126139
CHECK_AND_FILL_VEC_BPLUS_FULL(prong1, tpcNSigmaPi1, tpcNSigmaPi);
127140
// TOF PID variable
@@ -175,9 +188,9 @@ class HfMlResponseBplusToD0Pi : public HfMlResponse<TypeOutputScore>
175188
FILL_MAP_BPLUS(cpa),
176189
FILL_MAP_BPLUS(cpaXY),
177190
FILL_MAP_BPLUS(maxNormalisedDeltaIP),
178-
FILL_MAP_BPLUS(prong0MlScoreBkg),
179-
FILL_MAP_BPLUS(prong0MlScorePrompt),
180-
FILL_MAP_BPLUS(prong0MlScoreNonprompt),
191+
FILL_MAP_BPLUS(prong0MlProbBkg),
192+
FILL_MAP_BPLUS(prong0MlProbPrompt),
193+
FILL_MAP_BPLUS(prong0MlProbNonPrompt),
181194
// TPC PID variable
182195
FILL_MAP_BPLUS(tpcNSigmaPi1),
183196
// TOF PID variable
+197
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,197 @@
1+
// Copyright 2019-2020 CERN and copyright holders of ALICE O2.
2+
// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3+
// All rights not expressly granted are reserved.
4+
//
5+
// This software is distributed under the terms of the GNU General Public
6+
// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7+
//
8+
// In applying this license CERN does not waive the privileges and immunities
9+
// granted to it by virtue of its status as an Intergovernmental Organization
10+
// or submit itself to any jurisdiction.
11+
12+
/// \file HfMlResponseBplusToD0PiReduced.h
13+
/// \brief Class to compute the ML response for B± → D0(bar) π± analysis selections in the reduced format
14+
/// \author Antonio Palasciano <[email protected]>, INFN Bari
15+
16+
#ifndef PWGHF_CORE_HFMLRESPONSEBPLUSTOD0PIREDUCED_H_
17+
#define PWGHF_CORE_HFMLRESPONSEBPLUSTOD0PIREDUCED_H_
18+
19+
#include <map>
20+
#include <string>
21+
#include <vector>
22+
23+
#include "PWGHF/Core/HfMlResponse.h"
24+
#include "PWGHF/D2H/Utils/utilsRedDataFormat.h"
25+
26+
// Fill the map of available input features
27+
// the key is the feature's name (std::string)
28+
// the value is the corresponding value in EnumInputFeatures
29+
#define FILL_MAP_BPLUS(FEATURE) \
30+
{ \
31+
#FEATURE, static_cast<uint8_t>(InputFeaturesBplusToD0PiReduced::FEATURE) \
32+
}
33+
34+
// Check if the index of mCachedIndices (index associated to a FEATURE)
35+
// matches the entry in EnumInputFeatures associated to this FEATURE
36+
// if so, the inputFeatures vector is filled with the FEATURE's value
37+
// by calling the corresponding GETTER from OBJECT
38+
#define CHECK_AND_FILL_VEC_BPLUS_FULL(OBJECT, FEATURE, GETTER) \
39+
case static_cast<uint8_t>(InputFeaturesBplusToD0PiReduced::FEATURE): { \
40+
inputFeatures.emplace_back(OBJECT.GETTER()); \
41+
break; \
42+
}
43+
44+
// Check if the index of mCachedIndices (index associated to a FEATURE)
45+
// matches the entry in EnumInputFeatures associated to this FEATURE
46+
// if so, the inputFeatures vector is filled with the FEATURE's value
47+
// by calling the GETTER function taking OBJECT in argument
48+
#define CHECK_AND_FILL_VEC_BPLUS_FUNC(OBJECT, FEATURE, GETTER) \
49+
case static_cast<uint8_t>(InputFeaturesBplusToD0PiReduced::FEATURE): { \
50+
inputFeatures.emplace_back(GETTER(OBJECT)); \
51+
break; \
52+
}
53+
54+
// Specific case of CHECK_AND_FILL_VEC_BPLUS_FULL(OBJECT, FEATURE, GETTER)
55+
// where OBJECT is named candidate and FEATURE = GETTER
56+
#define CHECK_AND_FILL_VEC_BPLUS(GETTER) \
57+
case static_cast<uint8_t>(InputFeaturesBplusToD0PiReduced::GETTER): { \
58+
inputFeatures.emplace_back(candidate.GETTER()); \
59+
break; \
60+
}
61+
62+
namespace o2::analysis
63+
{
64+
65+
enum class InputFeaturesBplusToD0PiReduced : uint8_t {
66+
ptProng0 = 0,
67+
ptProng1,
68+
impactParameter0,
69+
impactParameter1,
70+
impactParameterProduct,
71+
chi2PCA,
72+
decayLength,
73+
decayLengthXY,
74+
decayLengthNormalised,
75+
decayLengthXYNormalised,
76+
cpa,
77+
cpaXY,
78+
maxNormalisedDeltaIP,
79+
prong0MlScoreBkg,
80+
prong0MlScorePrompt,
81+
prong0MlScoreNonprompt,
82+
tpcNSigmaPi1,
83+
tofNSigmaPi1,
84+
tpcTofNSigmaPi1
85+
};
86+
87+
template <typename TypeOutputScore = float>
88+
class HfMlResponseBplusToD0PiReduced : public HfMlResponse<TypeOutputScore>
89+
{
90+
public:
91+
/// Default constructor
92+
HfMlResponseBplusToD0PiReduced() = default;
93+
/// Default destructor
94+
virtual ~HfMlResponseBplusToD0PiReduced() = default;
95+
96+
/// Method to get the input features vector needed for ML inference
97+
/// \param candidate is the B+ candidate
98+
/// \param prong1 is the candidate's prong1
99+
/// \return inputFeatures vector
100+
template <bool withDmesMl, typename T1, typename T2>
101+
std::vector<float> getInputFeatures(T1 const& candidate,
102+
T2 const& prong1)
103+
{
104+
std::vector<float> inputFeatures;
105+
106+
for (const auto& idx : MlResponse<TypeOutputScore>::mCachedIndices) {
107+
if constexpr (withDmesMl) {
108+
switch (idx) {
109+
CHECK_AND_FILL_VEC_BPLUS(ptProng0);
110+
CHECK_AND_FILL_VEC_BPLUS(ptProng1);
111+
CHECK_AND_FILL_VEC_BPLUS(impactParameter0);
112+
CHECK_AND_FILL_VEC_BPLUS(impactParameter1);
113+
CHECK_AND_FILL_VEC_BPLUS(impactParameterProduct);
114+
CHECK_AND_FILL_VEC_BPLUS(chi2PCA);
115+
CHECK_AND_FILL_VEC_BPLUS(decayLength);
116+
CHECK_AND_FILL_VEC_BPLUS(decayLengthXY);
117+
CHECK_AND_FILL_VEC_BPLUS(decayLengthNormalised);
118+
CHECK_AND_FILL_VEC_BPLUS(decayLengthXYNormalised);
119+
CHECK_AND_FILL_VEC_BPLUS(cpa);
120+
CHECK_AND_FILL_VEC_BPLUS(cpaXY);
121+
CHECK_AND_FILL_VEC_BPLUS(maxNormalisedDeltaIP);
122+
CHECK_AND_FILL_VEC_BPLUS(prong0MlScoreBkg);
123+
CHECK_AND_FILL_VEC_BPLUS(prong0MlScorePrompt);
124+
CHECK_AND_FILL_VEC_BPLUS(prong0MlScoreNonprompt);
125+
// TPC PID variable
126+
CHECK_AND_FILL_VEC_BPLUS_FULL(prong1, tpcNSigmaPi1, tpcNSigmaPi);
127+
// TOF PID variable
128+
CHECK_AND_FILL_VEC_BPLUS_FULL(prong1, tofNSigmaPi1, tofNSigmaPi);
129+
// Combined PID variables
130+
CHECK_AND_FILL_VEC_BPLUS_FUNC(prong1, tpcTofNSigmaPi1, o2::pid_tpc_tof_utils::getTpcTofNSigmaPi1);
131+
}
132+
} else {
133+
switch (idx) {
134+
CHECK_AND_FILL_VEC_BPLUS(ptProng0);
135+
CHECK_AND_FILL_VEC_BPLUS(ptProng1);
136+
CHECK_AND_FILL_VEC_BPLUS(impactParameter0);
137+
CHECK_AND_FILL_VEC_BPLUS(impactParameter1);
138+
CHECK_AND_FILL_VEC_BPLUS(impactParameterProduct);
139+
CHECK_AND_FILL_VEC_BPLUS(chi2PCA);
140+
CHECK_AND_FILL_VEC_BPLUS(decayLength);
141+
CHECK_AND_FILL_VEC_BPLUS(decayLengthXY);
142+
CHECK_AND_FILL_VEC_BPLUS(decayLengthNormalised);
143+
CHECK_AND_FILL_VEC_BPLUS(decayLengthXYNormalised);
144+
CHECK_AND_FILL_VEC_BPLUS(cpa);
145+
CHECK_AND_FILL_VEC_BPLUS(cpaXY);
146+
CHECK_AND_FILL_VEC_BPLUS(maxNormalisedDeltaIP);
147+
// TPC PID variable
148+
CHECK_AND_FILL_VEC_BPLUS_FULL(prong1, tpcNSigmaPi1, tpcNSigmaPi);
149+
// TOF PID variable
150+
CHECK_AND_FILL_VEC_BPLUS_FULL(prong1, tofNSigmaPi1, tofNSigmaPi);
151+
// Combined PID variables
152+
CHECK_AND_FILL_VEC_BPLUS_FUNC(prong1, tpcTofNSigmaPi1, o2::pid_tpc_tof_utils::getTpcTofNSigmaPi1);
153+
}
154+
}
155+
}
156+
157+
return inputFeatures;
158+
}
159+
160+
protected:
161+
/// Method to fill the map of available input features
162+
void setAvailableInputFeatures()
163+
{
164+
MlResponse<TypeOutputScore>::mAvailableInputFeatures = {
165+
FILL_MAP_BPLUS(ptProng0),
166+
FILL_MAP_BPLUS(ptProng1),
167+
FILL_MAP_BPLUS(impactParameter0),
168+
FILL_MAP_BPLUS(impactParameter1),
169+
FILL_MAP_BPLUS(impactParameterProduct),
170+
FILL_MAP_BPLUS(chi2PCA),
171+
FILL_MAP_BPLUS(decayLength),
172+
FILL_MAP_BPLUS(decayLengthXY),
173+
FILL_MAP_BPLUS(decayLengthNormalised),
174+
FILL_MAP_BPLUS(decayLengthXYNormalised),
175+
FILL_MAP_BPLUS(cpa),
176+
FILL_MAP_BPLUS(cpaXY),
177+
FILL_MAP_BPLUS(maxNormalisedDeltaIP),
178+
FILL_MAP_BPLUS(prong0MlScoreBkg),
179+
FILL_MAP_BPLUS(prong0MlScorePrompt),
180+
FILL_MAP_BPLUS(prong0MlScoreNonprompt),
181+
// TPC PID variable
182+
FILL_MAP_BPLUS(tpcNSigmaPi1),
183+
// TOF PID variable
184+
FILL_MAP_BPLUS(tofNSigmaPi1),
185+
// Combined PID variable
186+
FILL_MAP_BPLUS(tpcTofNSigmaPi1)};
187+
}
188+
};
189+
190+
} // namespace o2::analysis
191+
192+
#undef FILL_MAP_BPLUS
193+
#undef CHECK_AND_FILL_VEC_BPLUS_FULL
194+
#undef CHECK_AND_FILL_VEC_BPLUS_FUNC
195+
#undef CHECK_AND_FILL_VEC_BPLUS
196+
197+
#endif // PWGHF_CORE_HFMLRESPONSEBPLUSTOD0PIREDUCED_H_

PWGHF/D2H/TableProducer/candidateSelectorB0ToDPiReduced.cxx

+1-1
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,7 @@ struct HfCandidateSelectorB0ToDPiReduced {
173173
}
174174

175175
if constexpr (withDmesMl) { // we include it in the topological selections
176-
if (!hfHelper.selectionDmesMlScoresForB(hfCandB0, cutsDmesMl, binsPtDmesMl)) {
176+
if (!hfHelper.selectionDmesMlScoresForBReduced(hfCandB0, cutsDmesMl, binsPtDmesMl)) {
177177
hfSelB0ToDPiCandidate(statusB0ToDPi);
178178
if (applyB0Ml) {
179179
hfMlB0ToDPiCandidate(outputMlNotPreselected);

PWGHF/D2H/TableProducer/candidateSelectorBplusToD0PiReduced.cxx

+3-3
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
#include "Common/Core/TrackSelectorPID.h"
2424

2525
#include "PWGHF/Core/HfHelper.h"
26-
#include "PWGHF/Core/HfMlResponseBplusToD0Pi.h"
26+
#include "PWGHF/Core/HfMlResponseBplusToD0PiReduced.h"
2727
#include "PWGHF/Core/SelectorCuts.h"
2828
#include "PWGHF/DataModel/CandidateReconstructionTables.h"
2929
#include "PWGHF/DataModel/CandidateSelectionTables.h"
@@ -78,7 +78,7 @@ struct HfCandidateSelectorBplusToD0PiReduced {
7878
int mySelectionFlagD0 = -1;
7979
int mySelectionFlagD0bar = -1;
8080

81-
o2::analysis::HfMlResponseBplusToD0Pi<float> hfMlResponse;
81+
o2::analysis::HfMlResponseBplusToD0PiReduced<float> hfMlResponse;
8282
float outputMlNotPreselected = -1.;
8383
std::vector<float> outputMl = {};
8484
o2::ccdb::CcdbApi ccdbApi;
@@ -174,7 +174,7 @@ struct HfCandidateSelectorBplusToD0PiReduced {
174174
}
175175

176176
if constexpr (withDmesMl) { // we include it in the topological selections
177-
if (!hfHelper.selectionDmesMlScoresForB(hfCandBp, cutsDmesMl, binsPtDmesMl)) {
177+
if (!hfHelper.selectionDmesMlScoresForBReduced(hfCandBp, cutsDmesMl, binsPtDmesMl)) {
178178
hfSelBplusToD0PiCandidate(statusBplus);
179179
if (applyBplusMl) {
180180
hfMlBplusToD0PiCandidate(outputMlNotPreselected);

PWGHF/D2H/TableProducer/candidateSelectorBsToDsPiReduced.cxx

+1-1
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ struct HfCandidateSelectorBsToDsPiReduced {
164164
}
165165

166166
if constexpr (withDmesMl) { // we include it in the topological selections
167-
if (!hfHelper.selectionDmesMlScoresForB(hfCandBs, cutsDmesMl, binsPtDmesMl)) {
167+
if (!hfHelper.selectionDmesMlScoresForBReduced(hfCandBs, cutsDmesMl, binsPtDmesMl)) {
168168
hfSelBsToDsPiCandidate(statusBsToDsPi);
169169
if (applyBsMl) {
170170
hfMlBsToDsPiCandidate(outputMl);

0 commit comments

Comments
 (0)