Skip to content

Commit 2e047f7

Browse files
committed
Adding new task for local mix candidate analysis in Dstar spin alignment measurement.
1 parent 97abd90 commit 2e047f7

2 files changed

Lines changed: 252 additions & 0 deletions

File tree

PWGHF/D2H/Tasks/CMakeLists.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,3 +178,8 @@ o2physics_add_dpl_workflow(task-deuteron-from-lb
178178
SOURCES taskDeuteronFromLb.cxx
179179
PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2Physics::EventFilteringUtils
180180
COMPONENT_NAME Analysis)
181+
182+
o2physics_add_dpl_workflow(task-mixing-dstar-cand-tree-creator
183+
SOURCES taskMixingDstarCandTreeCreator.cxx
184+
PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore
185+
COMPONENT_NAME Analysis)
Lines changed: 247 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,247 @@
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 taskMixingDstarCandTreeCreator.cxx
13+
/// \brief Writer of D*+ → D0 ( → π+ K-) π+ candidates in the form of flat tables to be stored in TTrees.
14+
/// Intended for Mix-candidate analysis in spin alignment measurement.
15+
/// Serving as a correction for detector acceptance and reconstruction efficiency.
16+
///
17+
/// \author Mingze li <mingze.li@cern.ch>, CCNU/UniTo
18+
19+
#include "PWGHF/Core/DecayChannels.h"
20+
#include "PWGHF/D2H/Utils/utilsFlow.h"
21+
#include "PWGHF/Core/CentralityEstimation.h"
22+
#include "PWGHF/DataModel/CandidateReconstructionTables.h"
23+
#include "PWGHF/DataModel/CandidateSelectionTables.h"
24+
25+
#include "Common/Core/RecoDecay.h"
26+
27+
#include <CommonConstants/PhysicsConstants.h>
28+
#include <Framework/ASoA.h>
29+
#include <Framework/AnalysisDataModel.h>
30+
#include <Framework/AnalysisHelpers.h>
31+
#include <Framework/AnalysisTask.h>
32+
#include <Framework/Configurable.h>
33+
#include <Framework/InitContext.h>
34+
#include <Framework/runDataProcessing.h>
35+
36+
#include <cstdint>
37+
38+
using namespace o2;
39+
using namespace o2::framework;
40+
using namespace o2::framework::expressions;
41+
using namespace o2::hf_centrality;
42+
using namespace o2::hf_occupancy;
43+
using namespace o2::analysis::hf_flow_utils;
44+
45+
namespace o2::aod
46+
{
47+
namespace mixing_dstar
48+
{
49+
DECLARE_SOA_INDEX_COLUMN(Collision, collision);
50+
// D0 related variables
51+
DECLARE_SOA_COLUMN(MD0, mD0, float);
52+
DECLARE_SOA_COLUMN(PtD0, ptD0, float);
53+
DECLARE_SOA_COLUMN(PD0, pD0, float);
54+
DECLARE_SOA_COLUMN(EtaD0, etaD0, float);
55+
DECLARE_SOA_COLUMN(PhiD0, phiD0, float);
56+
DECLARE_SOA_COLUMN(YD0, yD0, float);
57+
// soft pion related variables
58+
DECLARE_SOA_COLUMN(PtSoftPi, ptSoftPi, float);
59+
DECLARE_SOA_COLUMN(PSoftPi, pSoftPi, float);
60+
DECLARE_SOA_COLUMN(EtaSoftPi, etaSoftPi, float);
61+
DECLARE_SOA_COLUMN(PhiSoftPi, phiSoftPi, float);
62+
DECLARE_SOA_COLUMN(YSoftPi, ySoftPi, float);
63+
// Dstar related variables
64+
DECLARE_SOA_COLUMN(M, m, float);
65+
DECLARE_SOA_COLUMN(Pt, pt, float);
66+
DECLARE_SOA_COLUMN(P, p, float);
67+
DECLARE_SOA_COLUMN(Eta, eta, float);
68+
DECLARE_SOA_COLUMN(Phi, phi, float);
69+
DECLARE_SOA_COLUMN(Y, y, float);
70+
DECLARE_SOA_COLUMN(MlProbDstarToD0PiBkg, mlProbDstarToD0PiBkg, float);
71+
DECLARE_SOA_COLUMN(MlProbDstarToD0PiPrompt, mlProbDstarToD0PiPrompt, float);
72+
DECLARE_SOA_COLUMN(MlProbDstarToD0PiNonPrompt, mlProbDstarToD0PiNonPrompt, float);
73+
// Events
74+
DECLARE_SOA_COLUMN(ZVec, zVec, float);
75+
DECLARE_SOA_COLUMN(Centrality, centrality, float);
76+
DECLARE_SOA_COLUMN(Multiplicity, multiplicity, int);
77+
DECLARE_SOA_COLUMN(Occupancy, occupancy, int);
78+
DECLARE_SOA_COLUMN(XQvec, xqVec, float);
79+
DECLARE_SOA_COLUMN(YQvec, yqVec, float);
80+
DECLARE_SOA_COLUMN(GIndexCol, gIndexCol, int);
81+
DECLARE_SOA_COLUMN(TimeStamp, timeStamp, int64_t);
82+
// Tracks
83+
DECLARE_SOA_COLUMN(MinAbsEtaTrack, MinabsEtaTrack, float);
84+
DECLARE_SOA_COLUMN(MinNumItsCls, minNumItsCls, int);
85+
DECLARE_SOA_COLUMN(MinNumTpcCls, minNumTpcCls, int);
86+
} // namespace mixing_dstar
87+
88+
DECLARE_SOA_TABLE(HfCandDstMix, "AOD", "HFCANDDSTMIX",
89+
mixing_dstar::MD0,
90+
// mixing_dstar::PtD0,
91+
// mixing_dstar::EtaD0,
92+
// mixing_dstar::PhiD0,
93+
// mixing_dstar::YD0,
94+
mixing_dstar::PtSoftPi,
95+
mixing_dstar::EtaSoftPi,
96+
mixing_dstar::PhiSoftPi,
97+
// mixing_dstar::YSoftPi,
98+
mixing_dstar::M,
99+
mixing_dstar::Pt,
100+
mixing_dstar::Eta,
101+
mixing_dstar::Phi,
102+
mixing_dstar::Y,
103+
mixing_dstar::MlProbDstarToD0PiBkg,
104+
mixing_dstar::MlProbDstarToD0PiPrompt,
105+
mixing_dstar::MlProbDstarToD0PiNonPrompt,
106+
mixing_dstar::ZVec,
107+
mixing_dstar::Centrality,
108+
// mixing_dstar::Multiplicity,
109+
mixing_dstar::Occupancy,
110+
mixing_dstar::XQvec,
111+
mixing_dstar::YQvec,
112+
mixing_dstar::MinAbsEtaTrack,
113+
mixing_dstar::MinNumItsCls,
114+
mixing_dstar::MinNumTpcCls,
115+
mixing_dstar::GIndexCol,
116+
mixing_dstar::TimeStamp);
117+
} // namespace o2::aod
118+
119+
/// Writes the full information in an output TTree
120+
struct HfTaskMixingDstarCandTreeCreator {
121+
Produces<o2::aod::HfCandDstMix> rowCandidateMix;
122+
123+
Configurable<bool> selectionFlagDstarToD0Pi{"selectionFlagDstarToD0Pi", true, "Selection Flag for D* decay to D0 & Pi"};
124+
Configurable<bool> fillMixingCandidateTable{"fillMixingCandidateTable", false, "Switch to fill lite table with candidate properties"};
125+
126+
Configurable<int> qVecDetector{"qVecDetector", 2, "Detector for Q vector estimation (FV0A: 0, FT0M: 1, FT0C: 2)"};
127+
Configurable<int> centEstimator{"centEstimator", 2, "Centrality estimator ((None: 0, FT0C: 2, FT0M: 3))"};
128+
Configurable<int> occEstimator{"occEstimator", 2, "If enabled, replace number of PV contributors with occupancy estimation (0: don't use, 1: ITS, 2: FT0C)"};
129+
130+
131+
using CollsWithQVecs = soa::Join<aod::Collisions, aod::EvSels, aod::QvectorFT0Cs, aod::QvectorFT0As, aod::QvectorFT0Ms, aod::QvectorFV0As, aod::QvectorBPoss, aod::QvectorBNegs, aod::QvectorBTots, aod::CentFT0Ms, aod::CentFT0Cs>;
132+
using TracksWithExtra = soa::Join<aod::Tracks, aod::TracksExtra>;
133+
using CandDstarWSelFlag = soa::Join<aod::HfCandDstars, aod::HfSelDstarToD0Pi>;
134+
using FilteredCandDstarWSelFlagAndMl = soa::Filtered<soa::Join<CandDstarWSelFlag, aod::HfMlDstarToD0Pi>>;
135+
136+
Filter filterSelectDstarCandidates = aod::hf_sel_candidate_dstar::isSelDstarToD0Pi == selectionFlagDstarToD0Pi;
137+
138+
Preslice<FilteredCandDstarWSelFlagAndMl> dstarWithMlPerCollision = aod::hf_cand::collisionId;
139+
140+
void init(InitContext const&)
141+
{
142+
}
143+
144+
/// prongTracks is the vector of daughter tracks
145+
/// etaMin is the minimum eta
146+
/// nItsClsMin is the minumum number of clusters in ITS
147+
/// nTpcClsMin is the minumum number of clusters in TPC
148+
template <typename Trk>
149+
void getTrackingInfos(std::vector<Trk> const& prongTracks, float& etaMin, int& nItsClsMin, int& nTpcClsMin)
150+
{
151+
etaMin = 10.f;
152+
nItsClsMin = 10;
153+
nTpcClsMin = 1000;
154+
155+
for (const auto& track : prongTracks) {
156+
if (std::abs(track.eta()) < etaMin) {
157+
etaMin = std::abs(track.eta());
158+
}
159+
if (track.itsNCls() < nItsClsMin) {
160+
nItsClsMin = track.itsNCls();
161+
}
162+
if (track.tpcNClsCrossedRows() < nTpcClsMin) {
163+
nTpcClsMin = track.tpcNClsCrossedRows();
164+
}
165+
}
166+
}
167+
168+
template <typename CollType, typename T, typename Trk, typename BcType>
169+
void fillCandidateTable(CollType const& collision, const T& candidate, Trk const& /*tracks*/, BcType const& /*bcs*/)
170+
{
171+
const auto bc = collision.template bc_as<BcType>();
172+
const int64_t timeStamp = bc.timestamp();
173+
174+
float massD0{-1.f};
175+
float massDStar{-1.f};
176+
float etaSoftPi{-1.f};
177+
float phiSoftPi{-1.f};
178+
if (candidate.signSoftPi() > 0) {
179+
massD0 = candidate.invMassD0();
180+
massDStar = candidate.invMassDstar();
181+
} else {
182+
massD0 = candidate.invMassD0Bar();
183+
massDStar = candidate.invMassAntiDstar();
184+
}
185+
etaSoftPi = RecoDecay::eta(std::array{candidate.pxSoftPi(), candidate.pySoftPi(), candidate.pzSoftPi()});
186+
phiSoftPi = RecoDecay::phi(std::array{candidate.pxSoftPi(), candidate.pySoftPi(), candidate.pzSoftPi()});
187+
188+
float absEtaTrackMin{-1.f};
189+
int numItsClsMin{-1}, numTpcClsMin{-1};
190+
191+
auto trackProng0 = candidate.template prong0_as<Trk>();
192+
auto trackProng1 = candidate.template prong1_as<Trk>();
193+
auto trackProng2 = candidate.template prongPi_as<Trk>();
194+
getTrackingInfos(std::vector{trackProng0, trackProng1, trackProng2}, absEtaTrackMin, numItsClsMin, numTpcClsMin);
195+
std::array<float, 3> const Qvector = getQvec(collision, qVecDetector.value);
196+
197+
if (fillMixingCandidateTable) {
198+
rowCandidateMix(
199+
massD0,
200+
// candidate.ptD0(),
201+
// candidate.etaD0(),
202+
// candidate.phiD0(),
203+
// candidate.yD0(),
204+
candidate.ptSoftPi(),
205+
etaSoftPi,
206+
phiSoftPi,
207+
massDStar,
208+
candidate.pt(),
209+
candidate.eta(),
210+
candidate.phi(),
211+
candidate.y(constants::physics::MassDStar),
212+
candidate.mlProbDstarToD0Pi()[0],
213+
candidate.mlProbDstarToD0Pi()[1],
214+
candidate.mlProbDstarToD0Pi()[2],
215+
collision.posZ(),
216+
getCentralityColl(collision, centEstimator),
217+
getOccupancyColl(collision, occEstimator),
218+
Qvector[0],
219+
Qvector[1],
220+
absEtaTrackMin,
221+
numItsClsMin,
222+
numTpcClsMin,
223+
collision.globalIndex(),
224+
timeStamp);
225+
}
226+
}
227+
228+
void processData(CollsWithQVecs const& collisions,
229+
FilteredCandDstarWSelFlagAndMl const& dstarCandidates,
230+
TracksWithExtra const& tracks,
231+
aod::BCsWithTimestamps const& bcWithTimeStamps)
232+
{
233+
for (const auto& collision : collisions) {
234+
auto thisCollId = collision.globalIndex();
235+
auto groupedDstarCandidates = dstarCandidates.sliceBy(dstarWithMlPerCollision, thisCollId);
236+
for (const auto& dstarCandidate : groupedDstarCandidates) {
237+
fillCandidateTable(collision, dstarCandidate, tracks, bcWithTimeStamps);
238+
}
239+
}
240+
}
241+
PROCESS_SWITCH(HfTaskMixingDstarCandTreeCreator, processData, "Process data", true);
242+
};
243+
244+
WorkflowSpec defineDataProcessing(ConfigContext const& cfgc)
245+
{
246+
return WorkflowSpec{adaptAnalysisTask<HfTaskMixingDstarCandTreeCreator>(cfgc)};
247+
}

0 commit comments

Comments
 (0)