Skip to content

Commit f8b07da

Browse files
Mingze129alibuild
andauthored
[PWGHF] treeCreatorDstarSpinAlignMixing: Adding new task for local mix candidate analysis in Dstar spin alignment measurement. (AliceO2Group#16721)
Co-authored-by: ALICE Action Bot <alibuild@cern.ch>
1 parent e587889 commit f8b07da

2 files changed

Lines changed: 240 additions & 0 deletions

File tree

PWGHF/D2H/TableProducer/CMakeLists.txt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,3 +106,10 @@ o2physics_add_dpl_workflow(converter-reduced-3-prongs-ml
106106
SOURCES converterReducedHadronDausPid.cxx
107107
PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore
108108
COMPONENT_NAME Analysis)
109+
110+
# Tree creator
111+
112+
o2physics_add_dpl_workflow(tree-creator-dstar-spin-align-mixing
113+
SOURCES treeCreatorDstarSpinAlignMixing.cxx
114+
PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore
115+
COMPONENT_NAME Analysis)
Lines changed: 233 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,233 @@
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 treeCreatorDstarSpinAlignMixing.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/CentralityEstimation.h"
20+
#include "PWGHF/Core/DecayChannels.h"
21+
#include "PWGHF/D2H/Utils/utilsFlow.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(ZVtx, zVtx, float);
75+
DECLARE_SOA_COLUMN(Centrality, centrality, float);
76+
DECLARE_SOA_COLUMN(NPvContrib, nPvContrib, uint16_t);
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, uint8_t);
85+
DECLARE_SOA_COLUMN(MinNumTpcCls, minNumTpcCls, uint8_t);
86+
} // namespace mixing_dstar
87+
88+
DECLARE_SOA_TABLE(HfCandDstMix, "AOD", "HFCANDDSTMIX",
89+
mixing_dstar::MD0,
90+
mixing_dstar::PtSoftPi,
91+
mixing_dstar::EtaSoftPi,
92+
mixing_dstar::PhiSoftPi,
93+
mixing_dstar::M,
94+
mixing_dstar::Pt,
95+
mixing_dstar::Eta,
96+
mixing_dstar::Phi,
97+
mixing_dstar::Y,
98+
mixing_dstar::MlProbDstarToD0PiBkg,
99+
mixing_dstar::MlProbDstarToD0PiPrompt,
100+
mixing_dstar::MlProbDstarToD0PiNonPrompt,
101+
mixing_dstar::ZVtx,
102+
mixing_dstar::Centrality,
103+
mixing_dstar::NPvContrib,
104+
mixing_dstar::Occupancy,
105+
mixing_dstar::XQVec,
106+
mixing_dstar::YQVec,
107+
mixing_dstar::MinAbsEtaTrack,
108+
mixing_dstar::MinNumItsCls,
109+
mixing_dstar::MinNumTpcCls,
110+
mixing_dstar::GIndexCol,
111+
mixing_dstar::TimeStamp);
112+
} // namespace o2::aod
113+
114+
/// Writes the full information in an output TTree
115+
struct HfTreeCreatorDstarSpinAlignMixing {
116+
Produces<o2::aod::HfCandDstMix> rowCandidateMix;
117+
118+
Configurable<int> qVecDetector{"qVecDetector", 2, "Detector for Q vector estimation (FV0A: 0, FT0M: 1, FT0C: 2)"};
119+
Configurable<int> centEstimator{"centEstimator", 2, "Centrality estimator ((None: 0, FT0C: 2, FT0M: 3))"};
120+
Configurable<int> occEstimator{"occEstimator", 2, "If enabled, replace number of PV contributors with occupancy estimation (0: don't use, 1: ITS, 2: FT0C)"};
121+
122+
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>;
123+
using TracksWithExtra = soa::Join<aod::Tracks, aod::TracksExtra>;
124+
using CandDstarWSelFlag = soa::Join<aod::HfCandDstars, aod::HfSelDstarToD0Pi>;
125+
using FilteredCandDstarWSelFlagAndMl = soa::Filtered<soa::Join<CandDstarWSelFlag, aod::HfMlDstarToD0Pi>>;
126+
127+
Filter filterSelectDstarCandidates = aod::hf_sel_candidate_dstar::isSelDstarToD0Pi == true;
128+
129+
Preslice<FilteredCandDstarWSelFlagAndMl> dstarWithMlPerCollision = aod::hf_cand::collisionId;
130+
131+
void init(InitContext const&)
132+
{
133+
}
134+
135+
/// prongTracks is the vector of daughter tracks
136+
/// etaMin is the minimum eta
137+
/// nItsClsMin is the minumum number of clusters in ITS
138+
/// nTpcClsMin is the minumum number of clusters in TPC
139+
template <typename Trk>
140+
void getTrackingInfos(std::vector<Trk> const& prongTracks, float& etaMin, int& nItsClsMin, int& nTpcClsMin)
141+
{
142+
etaMin = 10.f;
143+
nItsClsMin = 10;
144+
nTpcClsMin = 1000;
145+
146+
for (const auto& track : prongTracks) {
147+
if (std::abs(track.eta()) < etaMin) {
148+
etaMin = std::abs(track.eta());
149+
}
150+
if (track.itsNCls() < nItsClsMin) {
151+
nItsClsMin = track.itsNCls();
152+
}
153+
if (track.tpcNClsCrossedRows() < nTpcClsMin) {
154+
nTpcClsMin = track.tpcNClsCrossedRows();
155+
}
156+
}
157+
}
158+
159+
template <typename CollType, typename T, typename Trk, typename BcType>
160+
void fillCandidateTable(CollType const& collision, const T& candidate, Trk const& /*tracks*/, BcType const& /*bcs*/)
161+
{
162+
const auto bc = collision.template bc_as<BcType>();
163+
const int64_t timeStamp = bc.timestamp();
164+
165+
float massD0{-1.f};
166+
float massDStar{-1.f};
167+
float etaSoftPi{-1.f};
168+
float phiSoftPi{-1.f};
169+
if (candidate.signSoftPi() > 0) {
170+
massD0 = candidate.invMassD0();
171+
massDStar = candidate.invMassDstar();
172+
} else {
173+
massD0 = candidate.invMassD0Bar();
174+
massDStar = candidate.invMassAntiDstar();
175+
}
176+
etaSoftPi = RecoDecay::eta(std::array{candidate.pxSoftPi(), candidate.pySoftPi(), candidate.pzSoftPi()});
177+
phiSoftPi = RecoDecay::phi(std::array{candidate.pxSoftPi(), candidate.pySoftPi(), candidate.pzSoftPi()});
178+
179+
float absEtaTrackMin{-1.f};
180+
int numItsClsMin{-1}, numTpcClsMin{-1};
181+
182+
auto trackProng0 = candidate.template prong0_as<Trk>();
183+
auto trackProng1 = candidate.template prong1_as<Trk>();
184+
auto trackProng2 = candidate.template prongPi_as<Trk>();
185+
getTrackingInfos(std::vector{trackProng0, trackProng1, trackProng2}, absEtaTrackMin, numItsClsMin, numTpcClsMin);
186+
std::array<float, 3> const Qvector = getQvec(collision, qVecDetector.value);
187+
188+
rowCandidateMix(
189+
massD0,
190+
candidate.ptSoftPi(),
191+
etaSoftPi,
192+
phiSoftPi,
193+
massDStar,
194+
candidate.pt(),
195+
candidate.eta(),
196+
candidate.phi(),
197+
candidate.y(constants::physics::MassDStar),
198+
candidate.mlProbDstarToD0Pi()[0],
199+
candidate.mlProbDstarToD0Pi()[1],
200+
candidate.mlProbDstarToD0Pi()[2],
201+
collision.posZ(),
202+
getCentralityColl(collision, centEstimator),
203+
collision.numContrib(),
204+
getOccupancyColl(collision, occEstimator),
205+
Qvector[0],
206+
Qvector[1],
207+
absEtaTrackMin,
208+
numItsClsMin,
209+
numTpcClsMin,
210+
collision.globalIndex(),
211+
timeStamp);
212+
}
213+
214+
void processData(CollsWithQVecs const& collisions,
215+
FilteredCandDstarWSelFlagAndMl const& dstarCandidates,
216+
TracksWithExtra const& tracks,
217+
aod::BCsWithTimestamps const& bcWithTimeStamps)
218+
{
219+
for (const auto& collision : collisions) {
220+
auto thisCollId = collision.globalIndex();
221+
auto groupedDstarCandidates = dstarCandidates.sliceBy(dstarWithMlPerCollision, thisCollId);
222+
for (const auto& dstarCandidate : groupedDstarCandidates) {
223+
fillCandidateTable(collision, dstarCandidate, tracks, bcWithTimeStamps);
224+
}
225+
}
226+
}
227+
PROCESS_SWITCH(HfTreeCreatorDstarSpinAlignMixing, processData, "Process data", true);
228+
};
229+
230+
WorkflowSpec defineDataProcessing(ConfigContext const& cfgc)
231+
{
232+
return WorkflowSpec{adaptAnalysisTask<HfTreeCreatorDstarSpinAlignMixing>(cfgc)};
233+
}

0 commit comments

Comments
 (0)