Skip to content

Commit f558b82

Browse files
authored
PWGHF: Add Bs tree creator (#3308)
1 parent 1579762 commit f558b82

3 files changed

Lines changed: 376 additions & 1 deletion

File tree

PWGHF/TableProducer/CMakeLists.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,11 @@ o2physics_add_dpl_workflow(tree-creator-bplus-to-d0-pi
157157
PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore
158158
COMPONENT_NAME Analysis)
159159

160+
o2physics_add_dpl_workflow(tree-creator-bs-to-ds-pi
161+
SOURCES treeCreatorBsToDsPi.cxx
162+
PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore
163+
COMPONENT_NAME Analysis)
164+
160165
o2physics_add_dpl_workflow(tree-creator-d0-to-k-pi
161166
SOURCES treeCreatorD0ToKPi.cxx
162167
PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore

PWGHF/TableProducer/candidateCreatorBs.cxx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ struct HfCandidateCreatorBs {
8484
Preslice<aod::TrackAssoc> trackIndicesPerCollision = aod::track_association::collisionId;
8585

8686
OutputObj<TH1F> hMassDsToKKPi{TH1F("hMassDsToKKPi", "D_{s} candidates;inv. mass (K K #pi) (GeV/#it{c}^{2});entries", 500, 0., 5.)};
87-
OutputObj<TH1F> hPtDs{TH1F("hPtDs", "D_{s}candidates;D_{s} candidate #it{p}_{T} (GeV/#it{c});entries", 100, 0., 10.)};
87+
OutputObj<TH1F> hPtDs{TH1F("hPtDs", "D_{s} candidates;D_{s} candidate #it{p}_{T} (GeV/#it{c});entries", 100, 0., 10.)};
8888
OutputObj<TH1F> hPtPion{TH1F("hPtPion", "#pi candidates;#pi candidate #it{p}_{T} (GeV/#it{c});entries", 100, 0., 10.)};
8989
OutputObj<TH1F> hCPADs{TH1F("hCPADs", "D_{s} candidates;D_{s} cosine of pointing angle;entries", 110, -1.1, 1.1)};
9090
OutputObj<TH1F> hMassBsToDsPi{TH1F("hMassBsToDsPi", "2-prong candidates;inv. mass (B_{s} #rightarrow D_{s}#pi #rightarrow KK#pi#pi) (GeV/#it{c}^{2});entries", 500, 3., 8.)};
Lines changed: 370 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,370 @@
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 treeCreatorBsToDsPi.cxx
13+
/// \brief Writer of Bs0 → Ds- π+ candidates in the form of flat tables to be stored in TTrees.
14+
/// Intended for debug, local optimization of analysis on small samples or ML training.
15+
/// The output tables are defined and filled in this file.
16+
/// \note Adapted from treeCreatorB0T0DPi.cxx
17+
/// \author Phil Stahlhut <phil.lennart.stahlhut@cern.ch>
18+
19+
#include "Framework/AnalysisTask.h"
20+
#include "Framework/runDataProcessing.h"
21+
22+
#include "PWGHF/DataModel/CandidateReconstructionTables.h"
23+
#include "PWGHF/DataModel/CandidateSelectionTables.h"
24+
25+
using namespace o2;
26+
using namespace o2::framework;
27+
using namespace o2::framework::expressions;
28+
using namespace o2::aod::hf_cand_bs;
29+
using namespace o2::aod::hf_sel_candidate_bs;
30+
31+
namespace o2::aod
32+
{
33+
namespace full
34+
{
35+
DECLARE_SOA_COLUMN(PtProng0, ptProng0, float); //! Transverse momentum of prong0 (GeV/c)
36+
DECLARE_SOA_COLUMN(PProng0, pProng0, float); //! Momentum of prong0 (GeV/c)
37+
DECLARE_SOA_COLUMN(ImpactParameterNormalised0, impactParameterNormalised0, float); //! Normalised impact parameter of prong0
38+
DECLARE_SOA_COLUMN(PtProng1, ptProng1, float); //! Transverse momentum of prong1 (GeV/c)
39+
DECLARE_SOA_COLUMN(PProng1, pProng1, float); //! Momentum of prong1 (in GeV/c)
40+
DECLARE_SOA_COLUMN(ImpactParameterNormalised1, impactParameterNormalised1, float); //! Normalised impact parameter of prong1
41+
DECLARE_SOA_COLUMN(CandidateSelFlag, candidateSelFlag, int); //! Selection flag of candidate (output of candidateSelector)
42+
DECLARE_SOA_COLUMN(M, m, float); //! Invariant mass of candidate (GeV/c2)
43+
DECLARE_SOA_COLUMN(Pt, pt, float); //! Transverse momentum of candidate (GeV/c)
44+
DECLARE_SOA_COLUMN(P, p, float); //! Momentum of candidate (GeV/c)
45+
DECLARE_SOA_COLUMN(Y, y, float); //! Rapidity of candidate
46+
DECLARE_SOA_COLUMN(Eta, eta, float); //! Pseudorapidity of candidate
47+
DECLARE_SOA_COLUMN(Phi, phi, float); //! Azimuth angle of candidate
48+
DECLARE_SOA_COLUMN(E, e, float); //! Energy of candidate (GeV)
49+
DECLARE_SOA_COLUMN(NSigTpcPi1, nSigTpcPi1, float); //! TPC Nsigma separation for prong1 with pion mass hypothesis
50+
DECLARE_SOA_COLUMN(NSigTofPi1, nSigTofPi1, float); //! TOF Nsigma separation for prong1 with pion mass hypothesis
51+
DECLARE_SOA_COLUMN(DecayLength, decayLength, float); //! Decay length of candidate (cm)
52+
DECLARE_SOA_COLUMN(DecayLengthXY, decayLengthXY, float); //! Transverse decay length of candidate (cm)
53+
DECLARE_SOA_COLUMN(DecayLengthNormalised, decayLengthNormalised, float); //! Normalised decay length of candidate
54+
DECLARE_SOA_COLUMN(DecayLengthXYNormalised, decayLengthXYNormalised, float); //! Normalised transverse decay length of candidate
55+
DECLARE_SOA_COLUMN(Cpa, cpa, float); //! Cosine pointing angle of candidate
56+
DECLARE_SOA_COLUMN(CpaXY, cpaXY, float); //! Cosine pointing angle of candidate in transverse plane
57+
DECLARE_SOA_COLUMN(MaxNormalisedDeltaIP, maxNormalisedDeltaIP, float); //! Maximum normalized difference between measured and expected impact parameter of candidate prongs
58+
DECLARE_SOA_COLUMN(Ct, ct, float); //! Proper lifetime time ctau of candidate (cm)
59+
// Events
60+
DECLARE_SOA_COLUMN(IsEventReject, isEventReject, int); //! Event rejection flag
61+
DECLARE_SOA_COLUMN(RunNumber, runNumber, int); //! Run number
62+
} // namespace full
63+
64+
DECLARE_SOA_TABLE(HfCandBsLites, "AOD", "HFCANDBSLITE",
65+
hf_cand::Chi2PCA,
66+
full::DecayLength,
67+
full::DecayLengthXY,
68+
full::DecayLengthNormalised,
69+
full::DecayLengthXYNormalised,
70+
full::PtProng0,
71+
full::PtProng1,
72+
hf_cand::ImpactParameter0,
73+
hf_cand::ImpactParameter1,
74+
full::NSigTpcPi1,
75+
full::NSigTofPi1,
76+
full::CandidateSelFlag,
77+
full::M,
78+
full::Pt,
79+
full::Cpa,
80+
full::CpaXY,
81+
full::MaxNormalisedDeltaIP,
82+
full::Eta,
83+
full::Phi,
84+
full::Y,
85+
hf_cand_bs::FlagMcMatchRec);
86+
87+
DECLARE_SOA_TABLE(HfCandBsFulls, "AOD", "HFCANDBSFULL",
88+
collision::BCId,
89+
collision::NumContrib,
90+
collision::PosX,
91+
collision::PosY,
92+
collision::PosZ,
93+
hf_cand::XSecondaryVertex,
94+
hf_cand::YSecondaryVertex,
95+
hf_cand::ZSecondaryVertex,
96+
hf_cand::ErrorDecayLength,
97+
hf_cand::ErrorDecayLengthXY,
98+
hf_cand::Chi2PCA,
99+
full::DecayLength,
100+
full::DecayLengthXY,
101+
full::DecayLengthNormalised,
102+
full::DecayLengthXYNormalised,
103+
full::ImpactParameterNormalised0,
104+
full::PtProng0,
105+
full::PProng0,
106+
full::ImpactParameterNormalised1,
107+
full::PtProng1,
108+
full::PProng1,
109+
hf_cand::PxProng0,
110+
hf_cand::PyProng0,
111+
hf_cand::PzProng0,
112+
hf_cand::PxProng1,
113+
hf_cand::PyProng1,
114+
hf_cand::PzProng1,
115+
hf_cand::ImpactParameter0,
116+
hf_cand::ImpactParameter1,
117+
hf_cand::ErrorImpactParameter0,
118+
hf_cand::ErrorImpactParameter1,
119+
full::NSigTpcPi1,
120+
full::NSigTofPi1,
121+
full::CandidateSelFlag,
122+
full::M,
123+
full::Pt,
124+
full::P,
125+
full::Cpa,
126+
full::CpaXY,
127+
full::MaxNormalisedDeltaIP,
128+
full::Ct,
129+
full::Eta,
130+
full::Phi,
131+
full::Y,
132+
full::E,
133+
hf_cand_bs::FlagMcMatchRec);
134+
135+
DECLARE_SOA_TABLE(HfCandBsFullEvs, "AOD", "HFCANDBSFULLEV",
136+
collision::BCId,
137+
collision::NumContrib,
138+
collision::PosX,
139+
collision::PosY,
140+
collision::PosZ,
141+
full::IsEventReject,
142+
full::RunNumber);
143+
144+
DECLARE_SOA_TABLE(HfCandBsFullPs, "AOD", "HFCANDBSFULLP",
145+
collision::BCId,
146+
full::Pt,
147+
full::Eta,
148+
full::Phi,
149+
full::Y,
150+
hf_cand_bs::FlagMcMatchGen);
151+
} // namespace o2::aod
152+
153+
/// Writes the full information in an output TTree
154+
struct HfTreeCreatorBsToDsPi {
155+
Produces<o2::aod::HfCandBsFulls> rowCandidateFull;
156+
Produces<o2::aod::HfCandBsFullEvs> rowCandidateFullEvents;
157+
Produces<o2::aod::HfCandBsFullPs> rowCandidateFullParticles;
158+
Produces<o2::aod::HfCandBsLites> rowCandidateLite;
159+
160+
Configurable<int> selectionFlagBs{"selectionBs", 1, "Selection Flag for Bs"};
161+
Configurable<bool> fillCandidateLiteTable{"fillCandidateLiteTable", false, "Switch to fill lite table with candidate properties"};
162+
// parameters for production of training samples
163+
Configurable<bool> fillOnlySignal{"fillOnlySignal", false, "Flag to fill derived tables with signal for ML trainings"};
164+
Configurable<bool> fillOnlyBackground{"fillOnlyBackground", false, "Flag to fill derived tables with background for ML trainings"};
165+
Configurable<float> downSampleBkgFactor{"downSampleBkgFactor", 1., "Fraction of background candidates to keep for ML trainings"};
166+
Configurable<float> ptMaxForDownSample{"ptMaxForDownSample", 10., "Maximum pt for the application of the downsampling factor"};
167+
168+
using SelectedCandidatesMc = soa::Filtered<soa::Join<aod::HfCandBs, aod::HfCandBsMcRec, aod::HfSelBsToDsPi>>;
169+
using TracksWPid = soa::Join<aod::Tracks, aod::TracksPidPi>;
170+
171+
Filter filterSelectCandidates = aod::hf_sel_candidate_bs::isSelBsToDsPi >= selectionFlagBs;
172+
173+
Partition<SelectedCandidatesMc> recSig = nabs(aod::hf_cand_bs::flagMcMatchRec) == (int8_t)BIT(BsToDsPiToKKPiPi);
174+
Partition<SelectedCandidatesMc> recBg = nabs(aod::hf_cand_bs::flagMcMatchRec) != (int8_t)BIT(BsToDsPiToKKPiPi);
175+
176+
void init(InitContext const&)
177+
{
178+
}
179+
180+
template <typename T>
181+
void fillEvent(const T& collision, int isEventReject, int runNumber)
182+
{
183+
rowCandidateFullEvents(
184+
collision.bcId(),
185+
collision.numContrib(),
186+
collision.posX(),
187+
collision.posY(),
188+
collision.posZ(),
189+
isEventReject,
190+
runNumber);
191+
}
192+
193+
template <bool doMc = false, typename T, typename U>
194+
void fillCandidateTable(const T& candidate, const U& prong1)
195+
{
196+
int8_t flagMc = 0;
197+
if constexpr (doMc) {
198+
flagMc = candidate.flagMcMatchRec();
199+
}
200+
if (fillCandidateLiteTable) {
201+
rowCandidateLite(
202+
candidate.chi2PCA(),
203+
candidate.decayLength(),
204+
candidate.decayLengthXY(),
205+
candidate.decayLengthNormalised(),
206+
candidate.decayLengthXYNormalised(),
207+
candidate.ptProng0(),
208+
candidate.ptProng1(),
209+
candidate.impactParameter0(),
210+
candidate.impactParameter1(),
211+
prong1.tpcNSigmaPi(),
212+
prong1.tofNSigmaPi(),
213+
candidate.isSelBsToDsPi(),
214+
invMassBsToDsPi(candidate),
215+
candidate.pt(),
216+
candidate.cpa(),
217+
candidate.cpaXY(),
218+
candidate.maxNormalisedDeltaIP(),
219+
candidate.eta(),
220+
candidate.phi(),
221+
yBs(candidate),
222+
flagMc);
223+
} else {
224+
rowCandidateFull(
225+
prong1.collision().bcId(),
226+
prong1.collision().numContrib(),
227+
candidate.posX(),
228+
candidate.posY(),
229+
candidate.posZ(),
230+
candidate.xSecondaryVertex(),
231+
candidate.ySecondaryVertex(),
232+
candidate.zSecondaryVertex(),
233+
candidate.errorDecayLength(),
234+
candidate.errorDecayLengthXY(),
235+
candidate.chi2PCA(),
236+
candidate.decayLength(),
237+
candidate.decayLengthXY(),
238+
candidate.decayLengthNormalised(),
239+
candidate.decayLengthXYNormalised(),
240+
candidate.impactParameterNormalised0(),
241+
candidate.ptProng0(),
242+
RecoDecay::p(candidate.pxProng0(), candidate.pyProng0(), candidate.pzProng0()),
243+
candidate.impactParameterNormalised1(),
244+
candidate.ptProng1(),
245+
RecoDecay::p(candidate.pxProng1(), candidate.pyProng1(), candidate.pzProng1()),
246+
candidate.pxProng0(),
247+
candidate.pyProng0(),
248+
candidate.pzProng0(),
249+
candidate.pxProng1(),
250+
candidate.pyProng1(),
251+
candidate.pzProng1(),
252+
candidate.impactParameter0(),
253+
candidate.impactParameter1(),
254+
candidate.errorImpactParameter0(),
255+
candidate.errorImpactParameter1(),
256+
prong1.tpcNSigmaPi(),
257+
prong1.tofNSigmaPi(),
258+
candidate.isSelBsToDsPi(),
259+
invMassBsToDsPi(candidate),
260+
candidate.pt(),
261+
candidate.p(),
262+
candidate.cpa(),
263+
candidate.cpaXY(),
264+
candidate.maxNormalisedDeltaIP(),
265+
ctBs(candidate),
266+
candidate.eta(),
267+
candidate.phi(),
268+
yBs(candidate),
269+
eBs(candidate),
270+
flagMc);
271+
}
272+
}
273+
274+
void processData(aod::Collisions const& collisions,
275+
soa::Filtered<soa::Join<aod::HfCandBs, aod::HfSelBsToDsPi>> const& candidates,
276+
TracksWPid const&)
277+
{
278+
// Filling event properties
279+
rowCandidateFullEvents.reserve(collisions.size());
280+
for (const auto& collision : collisions) {
281+
fillEvent(collision, 0, 1);
282+
}
283+
284+
// Filling candidate properties
285+
rowCandidateFull.reserve(candidates.size());
286+
if (fillCandidateLiteTable) {
287+
rowCandidateLite.reserve(candidates.size());
288+
}
289+
for (const auto& candidate : candidates) {
290+
if (fillOnlyBackground && downSampleBkgFactor < 1.) {
291+
float pseudoRndm = candidate.ptProng1() * 1000. - (int64_t)(candidate.ptProng1() * 1000);
292+
if (pseudoRndm >= downSampleBkgFactor && candidate.pt() < ptMaxForDownSample) {
293+
continue;
294+
}
295+
}
296+
auto prong1 = candidate.prong1_as<TracksWPid>();
297+
fillCandidateTable(candidate, prong1);
298+
}
299+
}
300+
301+
PROCESS_SWITCH(HfTreeCreatorBsToDsPi, processData, "Process data", true);
302+
303+
void processMc(aod::Collisions const& collisions,
304+
aod::McCollisions const&,
305+
SelectedCandidatesMc const& candidates,
306+
soa::Join<aod::McParticles, aod::HfCandBsMcGen> const& particles,
307+
TracksWPid const&)
308+
{
309+
// Filling event properties
310+
rowCandidateFullEvents.reserve(collisions.size());
311+
for (const auto& collision : collisions) {
312+
fillEvent(collision, 0, 1);
313+
}
314+
315+
// Filling candidate properties
316+
if (fillOnlySignal) {
317+
rowCandidateFull.reserve(recSig.size());
318+
if (fillCandidateLiteTable) {
319+
rowCandidateLite.reserve(recSig.size());
320+
}
321+
for (const auto& candidate : recSig) {
322+
auto prong1 = candidate.prong1_as<TracksWPid>();
323+
fillCandidateTable<true>(candidate, prong1);
324+
}
325+
} else if (fillOnlyBackground) {
326+
rowCandidateFull.reserve(recBg.size());
327+
if (fillCandidateLiteTable) {
328+
rowCandidateLite.reserve(recBg.size());
329+
}
330+
for (const auto& candidate : recBg) {
331+
float pseudoRndm = candidate.ptProng1() * 1000. - (int64_t)(candidate.ptProng1() * 1000);
332+
if (candidate.pt() < ptMaxForDownSample && pseudoRndm >= downSampleBkgFactor) {
333+
continue;
334+
}
335+
auto prong1 = candidate.prong1_as<TracksWPid>();
336+
fillCandidateTable<true>(candidate, prong1);
337+
}
338+
} else {
339+
rowCandidateFull.reserve(candidates.size());
340+
if (fillCandidateLiteTable) {
341+
rowCandidateLite.reserve(candidates.size());
342+
}
343+
for (const auto& candidate : candidates) {
344+
auto prong1 = candidate.prong1_as<TracksWPid>();
345+
fillCandidateTable<true>(candidate, prong1);
346+
}
347+
}
348+
349+
// Filling particle properties
350+
rowCandidateFullParticles.reserve(particles.size());
351+
for (const auto& particle : particles) {
352+
if (TESTBIT(std::abs(particle.flagMcMatchGen()), DecayTypeMc::BsToDsPiToKKPiPi)) {
353+
rowCandidateFullParticles(
354+
particle.mcCollision().bcId(),
355+
particle.pt(),
356+
particle.eta(),
357+
particle.phi(),
358+
RecoDecay::y(array{particle.px(), particle.py(), particle.pz()}, RecoDecay::getMassPDG(particle.pdgCode())),
359+
particle.flagMcMatchGen());
360+
}
361+
}
362+
}
363+
364+
PROCESS_SWITCH(HfTreeCreatorBsToDsPi, processMc, "Process MC", false);
365+
};
366+
367+
WorkflowSpec defineDataProcessing(ConfigContext const& cfgc)
368+
{
369+
return WorkflowSpec{adaptAnalysisTask<HfTreeCreatorBsToDsPi>(cfgc)};
370+
}

0 commit comments

Comments
 (0)