Skip to content

Commit 754dcbf

Browse files
Tao-Fangalibuildvkucera
authored
[PWGHF] Add ML selection for Xic0ToXiPiKf (#11388)
Co-authored-by: ALICE Action Bot <alibuild@cern.ch> Co-authored-by: Vít Kučera <vit.kucera@cern.ch>
1 parent 1b27145 commit 754dcbf

File tree

4 files changed

+201
-1
lines changed

4 files changed

+201
-1
lines changed
Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
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 HfMlResponseXic0ToXiPiKf.h
13+
/// \brief Class to compute the ML response for Ξc^0 → Ξ∓ π± kf analysis selections
14+
/// \author Tao Fang <tao.fang@cern.ch>, Central China Normal University
15+
16+
#ifndef PWGHF_CORE_HFMLRESPONSEXIC0TOXIPIKF_H_
17+
#define PWGHF_CORE_HFMLRESPONSEXIC0TOXIPIKF_H_
18+
19+
#include <vector>
20+
21+
#include "PWGHF/Core/HfMlResponse.h"
22+
23+
// Fill the map of available input features
24+
// the key is the feature's name (std::string)
25+
// the value is the corresponding value in EnumInputFeatures
26+
#define FILL_MAP_XIC0TOXIPIKF(FEATURE) \
27+
{ \
28+
#FEATURE, static_cast<uint8_t>(InputFeaturesXic0ToXiPiKf::FEATURE) \
29+
}
30+
31+
// Check if the index of mCachedIndices (index associated to a FEATURE)
32+
// matches the entry in EnumInputFeatures associated to this FEATURE
33+
// if so, the inputFeatures vector is filled with the FEATURE's value
34+
// by calling the corresponding GETTER from OBJECT
35+
#define CHECK_AND_FILL_VEC_XIC0TOXIPIKF_FULL(OBJECT, FEATURE, GETTER) \
36+
case static_cast<uint8_t>(InputFeaturesXic0ToXiPiKf::FEATURE): { \
37+
inputFeatures.emplace_back(OBJECT.GETTER()); \
38+
break; \
39+
}
40+
41+
// where OBJECT is named candidate and FEATURE = GETTER
42+
#define CHECK_AND_FILL_VEC_XIC0TOXIPIKF(GETTER) \
43+
case static_cast<uint8_t>(InputFeaturesXic0ToXiPiKf::GETTER): { \
44+
inputFeatures.emplace_back(candidate.GETTER()); \
45+
break; \
46+
}
47+
48+
namespace o2::analysis
49+
{
50+
51+
enum class InputFeaturesXic0ToXiPiKf : uint8_t {
52+
tpcNSigmaPiFromLambda,
53+
tpcNSigmaPiFromCasc,
54+
tpcNSigmaPiFromCharmBaryon,
55+
dcaCascDau,
56+
dcaCharmBaryonDau,
57+
kfDcaXYPiFromXic,
58+
kfDcaXYCascToPv,
59+
cascChi2OverNdf,
60+
xicChi2OverNdf,
61+
cascldl,
62+
chi2TopoCascToPv,
63+
chi2TopoCascToXic,
64+
cosPaCascToXic,
65+
decayLenXYCasc
66+
};
67+
68+
template <typename TypeOutputScore = float>
69+
class HfMlResponseXic0ToXiPiKf : public HfMlResponse<TypeOutputScore>
70+
{
71+
public:
72+
/// Default constructor
73+
HfMlResponseXic0ToXiPiKf() = default;
74+
/// Default destructor
75+
virtual ~HfMlResponseXic0ToXiPiKf() = default;
76+
77+
/// Method to get the input features vector needed for ML inference
78+
/// \param candidate is the Xic0 candidate
79+
/// \return inputFeatures vector
80+
template <typename T1, typename T2, typename T3>
81+
// std::vector<float> getInputFeatures(T1 const& candidate)
82+
std::vector<float> getInputFeatures(T1 const& candidate, T2 const& lamProngPi, T2 const& cascProngPi, T3 const& charmBaryonProngPi)
83+
{
84+
std::vector<float> inputFeatures;
85+
86+
for (const auto& idx : MlResponse<TypeOutputScore>::mCachedIndices) {
87+
switch (idx) {
88+
// PID variables
89+
CHECK_AND_FILL_VEC_XIC0TOXIPIKF_FULL(lamProngPi, tpcNSigmaPiFromLambda, tpcNSigmaPi);
90+
CHECK_AND_FILL_VEC_XIC0TOXIPIKF_FULL(cascProngPi, tpcNSigmaPiFromCasc, tpcNSigmaPi);
91+
CHECK_AND_FILL_VEC_XIC0TOXIPIKF_FULL(charmBaryonProngPi, tpcNSigmaPiFromCharmBaryon, tpcNSigmaPi);
92+
// DCA
93+
CHECK_AND_FILL_VEC_XIC0TOXIPIKF(dcaCascDau);
94+
CHECK_AND_FILL_VEC_XIC0TOXIPIKF(dcaCharmBaryonDau);
95+
CHECK_AND_FILL_VEC_XIC0TOXIPIKF(kfDcaXYPiFromXic);
96+
CHECK_AND_FILL_VEC_XIC0TOXIPIKF(kfDcaXYCascToPv);
97+
// Chi2Geo
98+
CHECK_AND_FILL_VEC_XIC0TOXIPIKF(cascChi2OverNdf);
99+
CHECK_AND_FILL_VEC_XIC0TOXIPIKF(xicChi2OverNdf);
100+
// ldl
101+
CHECK_AND_FILL_VEC_XIC0TOXIPIKF(cascldl);
102+
// Chi2Topo
103+
CHECK_AND_FILL_VEC_XIC0TOXIPIKF(chi2TopoCascToPv);
104+
CHECK_AND_FILL_VEC_XIC0TOXIPIKF(chi2TopoCascToXic);
105+
// CosPa
106+
CHECK_AND_FILL_VEC_XIC0TOXIPIKF(cosPaCascToXic);
107+
// Decay length
108+
CHECK_AND_FILL_VEC_XIC0TOXIPIKF(decayLenXYCasc);
109+
}
110+
}
111+
112+
return inputFeatures;
113+
}
114+
115+
protected:
116+
/// Method to fill the map of available input features
117+
void setAvailableInputFeatures()
118+
{
119+
MlResponse<TypeOutputScore>::mAvailableInputFeatures = {
120+
FILL_MAP_XIC0TOXIPIKF(tpcNSigmaPiFromLambda),
121+
FILL_MAP_XIC0TOXIPIKF(tpcNSigmaPiFromCasc),
122+
FILL_MAP_XIC0TOXIPIKF(tpcNSigmaPiFromCharmBaryon),
123+
FILL_MAP_XIC0TOXIPIKF(dcaCascDau),
124+
FILL_MAP_XIC0TOXIPIKF(dcaCharmBaryonDau),
125+
FILL_MAP_XIC0TOXIPIKF(kfDcaXYPiFromXic),
126+
FILL_MAP_XIC0TOXIPIKF(kfDcaXYCascToPv),
127+
FILL_MAP_XIC0TOXIPIKF(cascChi2OverNdf),
128+
FILL_MAP_XIC0TOXIPIKF(xicChi2OverNdf),
129+
FILL_MAP_XIC0TOXIPIKF(cascldl),
130+
FILL_MAP_XIC0TOXIPIKF(chi2TopoCascToPv),
131+
FILL_MAP_XIC0TOXIPIKF(chi2TopoCascToXic),
132+
FILL_MAP_XIC0TOXIPIKF(cosPaCascToXic),
133+
FILL_MAP_XIC0TOXIPIKF(decayLenXYCasc),
134+
};
135+
}
136+
};
137+
138+
} // namespace o2::analysis
139+
140+
#undef FILL_MAP_XIC0TOXIPIKF
141+
#undef CHECK_AND_FILL_VEC_XIC0TOXIPIKF_FULL
142+
#undef CHECK_AND_FILL_VEC_XIC0TOXIPIKF
143+
144+
#endif // PWGHF_CORE_HFMLRESPONSEXIC0TOXIPIKF_H_

PWGHF/DataModel/CandidateSelectionTables.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -350,6 +350,7 @@ DECLARE_SOA_COLUMN(TofNSigmaPiFromLambda, tofNSigmaPiFromLambda, float);
350350
DECLARE_SOA_COLUMN(TofNSigmaPrFromLambda, tofNSigmaPrFromLambda, float);
351351
DECLARE_SOA_COLUMN(PidTpcInfoStored, pidTpcInfoStored, int);
352352
DECLARE_SOA_COLUMN(PidTofInfoStored, pidTofInfoStored, int);
353+
DECLARE_SOA_COLUMN(MlProbToXiPi, mlProbToXiPi, std::vector<float>);
353354
} // namespace hf_sel_toxipi
354355

355356
DECLARE_SOA_TABLE(HfSelToXiPi, "AOD", "HFSELTOXIPI",
@@ -366,6 +367,9 @@ DECLARE_SOA_TABLE(HfSelToXiPiKf, "AOD", "HFSELTOXIPIKF",
366367
hf_sel_toxipi::TpcNSigmaPiFromCharmBaryon, hf_sel_toxipi::TpcNSigmaPiFromCasc, hf_sel_toxipi::TpcNSigmaPiFromLambda, hf_sel_toxipi::TpcNSigmaPrFromLambda,
367368
hf_sel_toxipi::TofNSigmaPiFromCharmBaryon, hf_sel_toxipi::TofNSigmaPiFromCasc, hf_sel_toxipi::TofNSigmaPiFromLambda, hf_sel_toxipi::TofNSigmaPrFromLambda);
368369

370+
DECLARE_SOA_TABLE(HfMlToXiPiKf, "AOD", "HFMLSELTOXIPIKF",
371+
hf_sel_toxipi::MlProbToXiPi);
372+
369373
namespace hf_sel_toomegapi
370374
{
371375
DECLARE_SOA_COLUMN(StatusPidLambda, statusPidLambda, bool);

PWGHF/TableProducer/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,7 @@ o2physics_add_dpl_workflow(candidate-selector-omegac0-to-omega-pi
174174

175175
o2physics_add_dpl_workflow(candidate-selector-xic0-to-xi-pi-kf
176176
SOURCES candidateSelectorXic0ToXiPiKf.cxx
177-
PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore
177+
PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2Physics::MLCore
178178
COMPONENT_NAME Analysis)
179179

180180
o2physics_add_dpl_workflow(candidate-selector-to-xi-pi

PWGHF/TableProducer/candidateSelectorXic0ToXiPiKf.cxx

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@
1212
/// \file candidateSelectorXic0ToXiPiKf.cxx
1313
/// \brief Xic0 → Xi Pi selection task
1414
/// \author Ran Tu <ran.tu@cern.ch>, Fudan University
15+
/// \author Tao Fang <tao.fang@cern.ch>, Central China Normal University
16+
17+
#include <string>
18+
#include <vector>
1519

1620
#include "CommonConstants/PhysicsConstants.h"
1721
#include "Framework/AnalysisTask.h"
@@ -20,6 +24,9 @@
2024
#include "Common/Core/TrackSelection.h"
2125
#include "Common/Core/TrackSelectorPID.h"
2226

27+
#include "PWGHF/Core/HfMlResponseXic0ToXiPiKf.h"
28+
#include "PWGHF/Core/SelectorCuts.h"
29+
2330
#include "PWGHF/DataModel/CandidateReconstructionTables.h"
2431
#include "PWGHF/DataModel/CandidateSelectionTables.h"
2532
#include "PWGHF/Utils/utilsAnalysis.h"
@@ -39,6 +46,7 @@ enum PidInfoStored {
3946
/// Struct for applying Xic0 -> Xi pi selection cuts
4047
struct HfCandidateSelectorXic0ToXiPiKf {
4148
Produces<aod::HfSelToXiPiKf> hfSelToXiPi;
49+
Produces<aod::HfMlToXiPiKf> hfMlToXiPi;
4250

4351
// LF analysis selections
4452
Configurable<double> radiusCascMin{"radiusCascMin", 0.5, "Min cascade radius"};
@@ -116,6 +124,25 @@ struct HfCandidateSelectorXic0ToXiPiKf {
116124
Configurable<int> nClustersItsInnBarrMin{"nClustersItsInnBarrMin", 1, "Minimum number of ITS clusters in inner barrel requirement for pi <- charm baryon"};
117125
Configurable<float> itsChi2PerClusterMax{"itsChi2PerClusterMax", 36, "Maximum value of chi2 fit over ITS clusters for pi <- charm baryon"};
118126

127+
// ML inference
128+
Configurable<bool> applyMl{"applyMl", true, "Flag to apply ML selections"};
129+
Configurable<std::vector<double>> binsPtMl{"binsPtMl", std::vector<double>{hf_cuts_ml::vecBinsPt}, "pT bin limits for ML application"};
130+
Configurable<std::vector<int>> cutDirMl{"cutDirMl", std::vector<int>{hf_cuts_ml::vecCutDir}, "Whether to reject score values greater or smaller than the threshold"};
131+
Configurable<LabeledArray<double>> cutsMl{"cutsMl", {hf_cuts_ml::Cuts[0], hf_cuts_ml::NBinsPt, hf_cuts_ml::NCutScores, hf_cuts_ml::labelsPt, hf_cuts_ml::labelsCutScore}, "ML selections per pT bin"};
132+
Configurable<int> nClassesMl{"nClassesMl", static_cast<int>(hf_cuts_ml::NCutScores), "Number of classes in ML model"};
133+
Configurable<std::vector<std::string>> namesInputFeatures{"namesInputFeatures", std::vector<std::string>{"feature1", "feature2"}, "Names of ML model input features"};
134+
135+
// CCDB configuration
136+
Configurable<std::string> ccdbUrl{"ccdbUrl", "http://alice-ccdb.cern.ch", "url of the ccdb repository"};
137+
Configurable<std::vector<std::string>> modelPathsCCDB{"modelPathsCCDB", std::vector<std::string>{"EventFiltering/PWGHF/BDTXic0ToXipiKf"}, "Paths of models on CCDB"};
138+
Configurable<std::vector<std::string>> onnxFileNames{"onnxFileNames", std::vector<std::string>{"ModelHandler_onnx_Xic0ToXipiKf.onnx"}, "ONNX file names for each pT bin (if not from CCDB full path)"};
139+
Configurable<int64_t> timestampCCDB{"timestampCCDB", -1, "timestamp of the ONNX file for ML model used to query in CCDB"};
140+
Configurable<bool> loadModelsFromCCDB{"loadModelsFromCCDB", false, "Flag to enable or disable the loading of models from CCDB"};
141+
142+
o2::analysis::HfMlResponseXic0ToXiPiKf<float> hfMlResponse;
143+
std::vector<float> outputMlXic0ToXiPiKf = {};
144+
o2::ccdb::CcdbApi ccdbApi;
145+
119146
TrackSelectorPr selectorProton;
120147
TrackSelectorPi selectorPion;
121148

@@ -176,6 +203,18 @@ struct HfCandidateSelectorXic0ToXiPiKf {
176203
registry.add("hSelMassCharmBaryon", "hSelMassCharmBaryon;status;entries", {HistType::kTH1D, {axisSel}});
177204
registry.add("hSelDcaXYToPvV0Daughters", "hSelDcaXYToPvV0Daughters;status;entries", {HistType::kTH1D, {axisSel}});
178205
registry.add("hSelDcaXYToPvPiFromCasc", "hSelDcaXYToPvPiFromCasc;status;entries", {HistType::kTH1D, {axisSel}});
206+
207+
if (applyMl) {
208+
hfMlResponse.configure(binsPtMl, cutsMl, cutDirMl, nClassesMl);
209+
if (loadModelsFromCCDB) {
210+
ccdbApi.init(ccdbUrl);
211+
hfMlResponse.setModelPathsCCDB(onnxFileNames, ccdbApi, modelPathsCCDB, timestampCCDB);
212+
} else {
213+
hfMlResponse.setModelPathsLocal(onnxFileNames);
214+
}
215+
hfMlResponse.cacheInputFeaturesIndices(namesInputFeatures);
216+
hfMlResponse.init();
217+
}
179218
}
180219

181220
void process(aod::HfCandToXiPiKf const& candidates,
@@ -186,6 +225,8 @@ struct HfCandidateSelectorXic0ToXiPiKf {
186225
// looping over charm baryon candidates
187226
for (const auto& candidate : candidates) {
188227

228+
auto ptCand = RecoDecay::pt(candidate.pxCharmBaryon(), candidate.pyCharmBaryon());
229+
189230
bool resultSelections = true; // True if the candidate passes all the selections, False otherwise
190231

191232
auto trackV0PosDauId = candidate.posTrackId(); // positive V0 daughter
@@ -503,6 +544,17 @@ struct HfCandidateSelectorXic0ToXiPiKf {
503544
registry.fill(HIST("hSelMassCharmBaryon"), 0);
504545
}
505546

547+
// ML selections
548+
if (applyMl) {
549+
bool isSelectedMlXic0 = false;
550+
std::vector<float> inputFeaturesXic0 = hfMlResponse.getInputFeatures(candidate, trackPiFromLam, trackPiFromCasc, trackPiFromCharm);
551+
isSelectedMlXic0 = hfMlResponse.isSelectedMl(inputFeaturesXic0, ptCand, outputMlXic0ToXiPiKf);
552+
if (!isSelectedMlXic0) {
553+
continue;
554+
}
555+
hfMlToXiPi(outputMlXic0ToXiPiKf);
556+
}
557+
506558
hfSelToXiPi(statusPidCharmBaryon, statusPidCascade, statusPidLambda, statusInvMassCharmBaryon, statusInvMassCascade, statusInvMassLambda, resultSelections, infoTpcStored, infoTofStored,
507559
trackPiFromCharm.tpcNSigmaPi(), trackPiFromCasc.tpcNSigmaPi(), trackPiFromLam.tpcNSigmaPi(), trackPrFromLam.tpcNSigmaPr(),
508560
trackPiFromCharm.tofNSigmaPi(), trackPiFromCasc.tofNSigmaPi(), trackPiFromLam.tofNSigmaPi(), trackPrFromLam.tofNSigmaPr());

0 commit comments

Comments
 (0)