Skip to content

Commit f63dc54

Browse files
prottayCMTProttay Das
andauthored
[PWGHF] code for v1 of D mesons using SP (AliceO2Group#8418)
Co-authored-by: Prottay Das <[email protected]>
1 parent 5288bd0 commit f63dc54

File tree

2 files changed

+245
-0
lines changed

2 files changed

+245
-0
lines changed

PWGHF/D2H/Tasks/CMakeLists.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,11 @@ o2physics_add_dpl_workflow(task-d0
5454
PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore
5555
COMPONENT_NAME Analysis)
5656

57+
o2physics_add_dpl_workflow(task-directed-flow-charm-hadrons
58+
SOURCES taskDirectedFlowCharmHadrons.cxx
59+
PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2Physics::EventFilteringUtils
60+
COMPONENT_NAME Analysis)
61+
5762
o2physics_add_dpl_workflow(task-dplus
5863
SOURCES taskDplus.cxx
5964
PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore
Lines changed: 240 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,240 @@
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 taskDirectedFlowCharmHadrons.cxx
13+
/// \brief Analysis task for charm hadron directed flow
14+
///
15+
/// \author Prottay Das, [email protected]
16+
17+
#include <string>
18+
#include <vector>
19+
#include <TMath.h>
20+
#include <cstdlib>
21+
22+
#include "CCDB/BasicCCDBManager.h"
23+
#include "Framework/AnalysisTask.h"
24+
#include "Framework/HistogramRegistry.h"
25+
#include "Framework/runDataProcessing.h"
26+
27+
#include "Common/Core/EventPlaneHelper.h"
28+
#include "PWGLF/DataModel/SPCalibrationTables.h"
29+
30+
#include "PWGHF/Core/HfHelper.h"
31+
#include "PWGHF/Core/CentralityEstimation.h"
32+
#include "PWGHF/DataModel/CandidateSelectionTables.h"
33+
#include "PWGHF/DataModel/CandidateReconstructionTables.h"
34+
#include "PWGHF/Utils/utilsEvSelHf.h"
35+
36+
using namespace o2;
37+
using namespace o2::aod;
38+
using namespace o2::framework;
39+
using namespace o2::framework::expressions;
40+
using namespace o2::hf_centrality;
41+
using namespace o2::hf_evsel;
42+
43+
enum DecayChannel { DplusToPiKPi = 0 };
44+
45+
struct HfTaskDirectedFlowCharmHadrons {
46+
Configurable<int> centEstimator{"centEstimator", 2, "Centrality estimation (FT0A: 1, FT0C: 2, FT0M: 3, FV0A: 4)"};
47+
Configurable<int> selectionFlag{"selectionFlag", 1, "Selection Flag for hadron (e.g. 1 for skimming, 3 for topo. and kine., 7 for PID)"};
48+
Configurable<float> centralityMin{"centralityMin", 0., "Minimum centrality accepted in SP computation"};
49+
Configurable<float> centralityMax{"centralityMax", 100., "Maximum centrality accepted in SP computation"};
50+
Configurable<bool> storeMl{"storeMl", false, "Flag to store ML scores"};
51+
Configurable<std::string> ccdbUrl{"ccdbUrl", "http://alice-ccdb.cern.ch", "url of the ccdb repository"};
52+
Configurable<std::vector<int>> classMl{"classMl", {0, 2}, "Indices of BDT scores to be stored. Two indexes max."};
53+
54+
ConfigurableAxis thnConfigAxisInvMass{"thnConfigAxisInvMass", {100, 1.78, 2.05}, ""};
55+
ConfigurableAxis thnConfigAxisPt{"thnConfigAxisPt", {VARIABLE_WIDTH, 0.2, 0.5, 1.0, 1.5, 2.0, 2.5, 3.0, 4.0, 5.0, 6.5, 8.0, 10.0}, ""};
56+
ConfigurableAxis thnConfigAxisEta{"thnConfigAxisEta", {VARIABLE_WIDTH, -0.8, -0.4, 0, 0.4, 0.8}, ""};
57+
ConfigurableAxis thnConfigAxisCent{"thnConfigAxisCent", {VARIABLE_WIDTH, 0.0, 10.0, 40.0, 80.0}, ""};
58+
ConfigurableAxis thnConfigAxisScalarProd{"thnConfigAxisScalarProd", {8000, -2.0, 2.0}, ""};
59+
ConfigurableAxis thnConfigAxisSign{"thnConfigAxisSign", {2, -2.0, 2.0}, ""};
60+
ConfigurableAxis thnConfigAxisMlOne{"thnConfigAxisMlOne", {1000, 0., 1.}, ""};
61+
ConfigurableAxis thnConfigAxisMlTwo{"thnConfigAxisMlTwo", {1000, 0., 1.}, ""};
62+
63+
using CandDplusDataWMl = soa::Filtered<soa::Join<aod::HfCand3Prong, aod::HfSelDplusToPiKPi, aod::HfMlDplusToPiKPi>>;
64+
using CandDplusData = soa::Filtered<soa::Join<aod::HfCand3Prong, aod::HfSelDplusToPiKPi>>;
65+
using CollsWithQvecs = soa::Join<aod::Collisions, aod::EvSels, aod::CentFV0As, aod::CentFT0Ms, aod::CentFT0As, aod::CentFT0Cs, aod::SPCalibrationTables>;
66+
using TracksWithExtra = soa::Join<aod::Tracks, aod::TracksExtra>;
67+
68+
Filter filterSelectDplusCandidates = aod::hf_sel_candidate_dplus::isSelDplusToPiKPi >= selectionFlag;
69+
70+
SliceCache cache;
71+
HfHelper hfHelper;
72+
EventPlaneHelper epHelper;
73+
HfEventSelection hfEvSel; // event selection and monitoring
74+
o2::framework::Service<o2::ccdb::BasicCCDBManager> ccdb;
75+
76+
HistogramRegistry registry{"registry", {}, OutputObjHandlingPolicy::AnalysisObject};
77+
78+
void init(InitContext&)
79+
{
80+
81+
/// check process functions
82+
std::array<int, 2> processes = {doprocessDplusStd, doprocessDplusMl};
83+
const int nProcesses = std::accumulate(processes.begin(), processes.end(), 0);
84+
if (nProcesses > 1) {
85+
LOGP(fatal, "Only one process function should be enabled at a time, please check your configuration");
86+
} else if (nProcesses == 0) {
87+
LOGP(fatal, "No process function enabled");
88+
}
89+
90+
const AxisSpec thnAxisInvMass{thnConfigAxisInvMass, "Inv. mass (GeV/#it{c}^{2})"};
91+
const AxisSpec thnAxisPt{thnConfigAxisPt, "#it{p}_{T} (GeV/#it{c})"};
92+
const AxisSpec thnAxisEta{thnConfigAxisEta, "#it{#eta}"};
93+
const AxisSpec thnAxisCent{thnConfigAxisCent, "Centrality"};
94+
const AxisSpec thnAxisScalarProd{thnConfigAxisScalarProd, "SP"};
95+
const AxisSpec thnAxisSign{thnConfigAxisSign, "Sign"};
96+
const AxisSpec thnAxisMlOne{thnConfigAxisMlOne, "Bkg score"};
97+
const AxisSpec thnAxisMlTwo{thnConfigAxisMlTwo, "FD score"};
98+
99+
std::vector<AxisSpec> axes = {thnAxisInvMass, thnAxisCent, thnAxisPt, thnAxisEta, thnAxisScalarProd, thnAxisSign};
100+
if (storeMl) {
101+
axes.insert(axes.end(), {thnAxisMlOne, thnAxisMlTwo});
102+
}
103+
registry.add("hpuxQxpvscentpteta", "hpuxQxpvscentpteta", HistType::kTHnSparseF, axes, true);
104+
registry.add("hpuyQypvscentpteta", "hpuyQypvscentpteta", HistType::kTHnSparseF, axes, true);
105+
registry.add("hpuxQxtvscentpteta", "hpuxQxtvscentpteta", HistType::kTHnSparseF, axes, true);
106+
registry.add("hpuyQytvscentpteta", "hpuyQytvscentpteta", HistType::kTHnSparseF, axes, true);
107+
108+
registry.add("hpQxtQxpvscent", "hpQxtQxpvscent", HistType::kTHnSparseF, {thnAxisCent, thnAxisScalarProd}, true);
109+
registry.add("hpQytQypvscent", "hpQytQypvscent", HistType::kTHnSparseF, {thnAxisCent, thnAxisScalarProd}, true);
110+
registry.add("hpQxtQypvscent", "hpQxtQypvscent", HistType::kTHnSparseF, {thnAxisCent, thnAxisScalarProd}, true);
111+
registry.add("hpQxpQytvscent", "hpQxpQytvscent", HistType::kTHnSparseF, {thnAxisCent, thnAxisScalarProd}, true);
112+
113+
ccdb->setURL(ccdbUrl);
114+
ccdb->setCaching(true);
115+
ccdb->setLocalObjectValidityChecking();
116+
}; // end init
117+
118+
/// Get the centrality
119+
/// \param collision is the collision with the centrality information
120+
double getCentrality(CollsWithQvecs::iterator const& collision)
121+
{
122+
double cent = -999.;
123+
switch (centEstimator) {
124+
case CentralityEstimator::FV0A:
125+
cent = collision.centFV0A();
126+
break;
127+
case CentralityEstimator::FT0M:
128+
cent = collision.centFT0M();
129+
break;
130+
case CentralityEstimator::FT0A:
131+
cent = collision.centFT0A();
132+
break;
133+
case CentralityEstimator::FT0C:
134+
cent = collision.centFT0C();
135+
break;
136+
default:
137+
LOG(warning) << "Centrality estimator not valid. Possible values are V0A, T0M, T0A, T0C. Fallback to V0A";
138+
cent = collision.centFV0A();
139+
break;
140+
}
141+
return cent;
142+
}
143+
144+
/// Compute the scalar product
145+
/// \param collision is the collision with the Q vector information and event plane
146+
/// \param candidates are the selected candidates
147+
template <DecayChannel channel, typename T1, typename Trk>
148+
void runFlowAnalysis(CollsWithQvecs::iterator const& collision,
149+
T1 const& candidates,
150+
Trk const& /*tracks*/)
151+
{
152+
double cent = getCentrality(collision);
153+
if (cent < centralityMin || cent > centralityMax) {
154+
return;
155+
}
156+
157+
if (!collision.triggerevent()) { // for selecting only callibrated events
158+
return;
159+
}
160+
161+
auto qxZDCA = collision.qxZDCA();
162+
auto qyZDCA = collision.qyZDCA();
163+
auto qxZDCC = collision.qxZDCC(); // extracting q vectors of ZDC
164+
auto qyZDCC = collision.qyZDCC();
165+
166+
auto QxtQxp = qxZDCC * qxZDCA;
167+
auto QytQyp = qyZDCC * qyZDCA;
168+
auto QxpQyt = qxZDCA * qyZDCC;
169+
auto QxtQyp = qxZDCC * qyZDCA;
170+
171+
// correlations in the denominators for SP calculation
172+
registry.fill(HIST("hpQxtQxpvscent"), cent, QxtQxp);
173+
registry.fill(HIST("hpQytQypvscent"), cent, QytQyp);
174+
registry.fill(HIST("hpQxpQytvscent"), cent, QxpQyt);
175+
registry.fill(HIST("hpQxtQypvscent"), cent, QxtQyp);
176+
177+
for (const auto& candidate : candidates) {
178+
double massCand = 0.;
179+
std::vector<double> outputMl = {-999., -999.};
180+
if constexpr (std::is_same_v<T1, CandDplusData> || std::is_same_v<T1, CandDplusDataWMl>) {
181+
massCand = hfHelper.invMassDplusToPiKPi(candidate);
182+
if constexpr (std::is_same_v<T1, CandDplusDataWMl>) {
183+
for (unsigned int iclass = 0; iclass < classMl->size(); iclass++)
184+
outputMl[iclass] = candidate.mlProbDplusToPiKPi()[classMl->at(iclass)];
185+
}
186+
}
187+
188+
auto trackprong0 = candidate.template prong0_as<Trk>();
189+
double sign = trackprong0.sign(); // to differentiate between D+ and D-
190+
191+
double ptCand = candidate.pt();
192+
double etaCand = candidate.eta();
193+
double phiCand = candidate.phi();
194+
double cosNPhi = std::cos(phiCand);
195+
double sinNPhi = std::sin(phiCand);
196+
197+
auto ux = cosNPhi; // real part of candidate q vector
198+
auto uy = sinNPhi; // imaginary part of candidate q vector
199+
auto uxQxp = ux * qxZDCA;
200+
auto uyQyp = uy * qyZDCA; // correlations of particle and ZDC q vectors
201+
auto uxQxt = ux * qxZDCC;
202+
auto uyQyt = uy * qyZDCC;
203+
204+
if (storeMl) {
205+
registry.fill(HIST("hpuxQxpvscentpteta"), massCand, cent, ptCand, etaCand, uxQxp, sign, outputMl[0], outputMl[1]);
206+
registry.fill(HIST("hpuyQypvscentpteta"), massCand, cent, ptCand, etaCand, uyQyp, sign, outputMl[0], outputMl[1]);
207+
registry.fill(HIST("hpuxQxtvscentpteta"), massCand, cent, ptCand, etaCand, uxQxt, sign, outputMl[0], outputMl[1]);
208+
registry.fill(HIST("hpuyQytvscentpteta"), massCand, cent, ptCand, etaCand, uyQyt, sign, outputMl[0], outputMl[1]);
209+
} else {
210+
registry.fill(HIST("hpuxQxpvscentpteta"), massCand, cent, ptCand, etaCand, uxQxp, sign);
211+
registry.fill(HIST("hpuyQypvscentpteta"), massCand, cent, ptCand, etaCand, uyQyp, sign);
212+
registry.fill(HIST("hpuxQxtvscentpteta"), massCand, cent, ptCand, etaCand, uxQxt, sign);
213+
registry.fill(HIST("hpuyQytvscentpteta"), massCand, cent, ptCand, etaCand, uyQyt, sign);
214+
}
215+
}
216+
}
217+
// Dplus with ML
218+
void processDplusMl(CollsWithQvecs::iterator const& collision,
219+
CandDplusDataWMl const& candidatesDplus,
220+
TracksWithExtra const& tracks)
221+
{
222+
runFlowAnalysis<DecayChannel::DplusToPiKPi>(collision, candidatesDplus, tracks);
223+
}
224+
PROCESS_SWITCH(HfTaskDirectedFlowCharmHadrons, processDplusMl, "Process Dplus candidates with ML", false);
225+
226+
// Dplus with rectangular cuts
227+
void processDplusStd(CollsWithQvecs::iterator const& collision,
228+
CandDplusData const& candidatesDplus,
229+
TracksWithExtra const& tracks)
230+
{
231+
runFlowAnalysis<DecayChannel::DplusToPiKPi>(collision, candidatesDplus, tracks);
232+
}
233+
PROCESS_SWITCH(HfTaskDirectedFlowCharmHadrons, processDplusStd, "Process Dplus candidates with rectangular cuts", true);
234+
235+
}; // End struct HfTaskDirectedFlowCharmHadrons
236+
237+
WorkflowSpec defineDataProcessing(ConfigContext const& cfgc)
238+
{
239+
return WorkflowSpec{adaptAnalysisTask<HfTaskDirectedFlowCharmHadrons>(cfgc)};
240+
}

0 commit comments

Comments
 (0)