Skip to content

Commit 85a91ce

Browse files
authored
Add track-V0 task (#370)
1 parent 75d83c7 commit 85a91ce

2 files changed

Lines changed: 294 additions & 0 deletions

File tree

PWGCF/FemtoDream/CMakeLists.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,11 @@ o2physics_add_dpl_workflow(femtodream-pair-track-track
1919
PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore
2020
COMPONENT_NAME Analysis)
2121

22+
o2physics_add_dpl_workflow(femtodream-pair-track-v0
23+
SOURCES femtoDreamPairTaskTrackV0.cxx
24+
PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore
25+
COMPONENT_NAME Analysis)
26+
2227
o2physics_add_dpl_workflow(femtodream-hash
2328
SOURCES femtoDreamHashTask.cxx
2429
PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore
Lines changed: 289 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,289 @@
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 femtoDreamPairTaskTrackTrack.cxx
13+
/// \brief Tasks that reads the track tables used for the pairing and builds pairs of two tracks
14+
/// \author Andi Mathis, TU München, andreas.mathis@ph.tum.de
15+
16+
#include "PWGCF/DataModel/FemtoDerived.h"
17+
#include "FemtoDreamParticleHisto.h"
18+
#include "FemtoDreamEventHisto.h"
19+
#include "FemtoDreamPairCleaner.h"
20+
#include "FemtoDreamContainer.h"
21+
#include "FemtoDreamDetaDphiStar.h"
22+
#include "Framework/AnalysisTask.h"
23+
#include "Framework/runDataProcessing.h"
24+
#include "Framework/HistogramRegistry.h"
25+
#include "Framework/ASoAHelpers.h"
26+
27+
using namespace o2;
28+
using namespace o2::analysis::femtoDream;
29+
using namespace o2::framework;
30+
using namespace o2::framework::expressions;
31+
32+
namespace
33+
{
34+
static constexpr int nCuts = 4;
35+
static const std::vector<std::string> cutNames{"MaxPt", "PIDthr", "nSigmaTPC", "nSigmaTPCTOF"};
36+
static const float cutsArray[nCuts] = {4.05f, 0.75f, 3.f, 3.f};
37+
38+
static constexpr int nNsigma = 3;
39+
static constexpr float kNsigma[nNsigma] = {3.5f, 3.f, 2.5f};
40+
41+
enum kPIDselection {
42+
k3d5sigma = 0,
43+
k3sigma = 1,
44+
k2d5sigma = 2
45+
};
46+
47+
enum kDetector {
48+
kTPC = 0,
49+
kTPCTOF = 1,
50+
kNdetectors = 2
51+
};
52+
} // namespace
53+
54+
struct femtoDreamPairTaskTrackV0 {
55+
56+
/// Particle 1 (track)
57+
Configurable<int> ConfPDGCodePartOne{"ConfPDGCodePartOne", 2212, "Particle 1 - PDG code"};
58+
Configurable<int> ConfCutPartOne{"ConfCutPartOne", 5542986, "Particle 1 - Selection bit from cutCulator"};
59+
Configurable<std::vector<int>> ConfPIDPartOne{"ConfPIDPartOne", std::vector<int>{2}, "Particle 1 - Read from cutCulator"}; // we also need the possibility to specify whether the bit is true/false ->std>>vector<std::pair<int, int>>int>>
60+
Configurable<LabeledArray<float>> cfgCutArray{"cfgCutArray", {cutsArray, nCuts, cutNames}, "Particle selections"};
61+
Configurable<int> cfgNspecies{"ccfgNspecies", 4, "Number of particle spieces with PID info"};
62+
63+
/// Partition for particle 1
64+
Partition<aod::FemtoDreamParticles> partsOne = (aod::femtodreamparticle::partType == uint8_t(aod::femtodreamparticle::ParticleType::kTrack)) &&
65+
(aod::femtodreamparticle::pt < cfgCutArray->get("MaxPt")) &&
66+
((aod::femtodreamparticle::cut & aod::femtodreamparticle::cutContainerType(ConfCutPartOne)) == aod::femtodreamparticle::cutContainerType(ConfCutPartOne));
67+
68+
/// Histogramming for particle 1
69+
FemtoDreamParticleHisto<aod::femtodreamparticle::ParticleType::kTrack, 1> trackHistoPartOne;
70+
71+
/// Particle 2 (V0)
72+
Configurable<int> ConfPDGCodePartTwo{"ConfPDGCodePartTwo", 3122, "Particle 1 - PDG code"};
73+
Configurable<int> ConfCutPartTwo{"ConfCutPartTwo", 338, "Particle 2 - Selection bit"};
74+
75+
/// Partition for particle 2
76+
Partition<aod::FemtoDreamParticles> partsTwo = (aod::femtodreamparticle::partType == uint8_t(aod::femtodreamparticle::ParticleType::kV0)) &&
77+
((aod::femtodreamparticle::cut & aod::femtodreamparticle::cutContainerType(ConfCutPartTwo)) == aod::femtodreamparticle::cutContainerType(ConfCutPartTwo));
78+
79+
/// Histogramming for particle 2
80+
FemtoDreamParticleHisto<aod::femtodreamparticle::ParticleType::kV0, 2> trackHistoPartTwo;
81+
82+
/// Histogramming for Event
83+
FemtoDreamEventHisto eventHisto;
84+
85+
/// The configurables need to be passed to an std::vector
86+
std::vector<int> vPIDPartOne;
87+
88+
/// Correlation part
89+
ConfigurableAxis CfgMultBins{"CfgMultBins", {VARIABLE_WIDTH, 0.0f, 20.0f, 40.0f, 60.0f, 80.0f, 100.0f, 200.0f, 99999.f}, "Mixing bins - multiplicity"};
90+
ConfigurableAxis CfgkstarBins{"CfgkstarBins", {1500, 0., 6.}, "binning kstar"};
91+
ConfigurableAxis CfgkTBins{"CfgkTBins", {150, 0., 9.}, "binning kT"};
92+
ConfigurableAxis CfgmTBins{"CfgmTBins", {225, 0., 7.5}, "binning mT"};
93+
Configurable<int> ConfNEventsMix{"ConfNEventsMix", 5, "Number of events for mixing"};
94+
Configurable<bool> ConfIsCPR{"ConfIsCPR", true, "Close Pair Rejection"};
95+
Configurable<float> ConfBField{"ConfBField", +0.5, "Magnetic Field"};
96+
97+
FemtoDreamContainer<femtoDreamContainer::EventType::same, femtoDreamContainer::Observable::kstar> sameEventCont;
98+
FemtoDreamContainer<femtoDreamContainer::EventType::mixed, femtoDreamContainer::Observable::kstar> mixedEventCont;
99+
FemtoDreamPairCleaner<aod::femtodreamparticle::ParticleType::kTrack, aod::femtodreamparticle::ParticleType::kV0> pairCleaner;
100+
FemtoDreamDetaDphiStar<aod::femtodreamparticle::ParticleType::kTrack, aod::femtodreamparticle::ParticleType::kV0> pairCloseRejection;
101+
/// Histogram output
102+
HistogramRegistry qaRegistry{"TrackQA", {}, OutputObjHandlingPolicy::AnalysisObject};
103+
HistogramRegistry resultRegistry{"Correlations", {}, OutputObjHandlingPolicy::AnalysisObject};
104+
105+
void init(InitContext&)
106+
{
107+
eventHisto.init(&qaRegistry);
108+
trackHistoPartOne.init(&qaRegistry);
109+
trackHistoPartTwo.init(&qaRegistry);
110+
111+
sameEventCont.init(&resultRegistry, CfgkstarBins, CfgMultBins, CfgkTBins, CfgmTBins);
112+
sameEventCont.setPDGCodes(ConfPDGCodePartOne, ConfPDGCodePartTwo);
113+
mixedEventCont.init(&resultRegistry, CfgkstarBins, CfgMultBins, CfgkTBins, CfgmTBins);
114+
mixedEventCont.setPDGCodes(ConfPDGCodePartOne, ConfPDGCodePartTwo);
115+
pairCleaner.init(&qaRegistry);
116+
if (ConfIsCPR) {
117+
pairCloseRejection.init(&resultRegistry, &qaRegistry, 0.01, 0.01, ConfBField, false); /// \todo add config for Δη and ΔΦ cut values
118+
}
119+
120+
vPIDPartOne = ConfPIDPartOne;
121+
}
122+
123+
/// internal function that returns the kPIDselection element corresponding to a specifica n-sigma value
124+
/// \param number of sigmas for PIF
125+
/// \return kPIDselection corresponing to n-sigma
126+
kPIDselection getPIDselection(float nSigma)
127+
{
128+
for (int i = 0; i < nNsigma; i++) {
129+
if (abs(nSigma - kNsigma[i]) < 1e-3) {
130+
return static_cast<kPIDselection>(i);
131+
}
132+
}
133+
LOG(info) << "Invalid value of nSigma: " << nSigma << ". Standard 3 sigma returned." << std::endl;
134+
return kPIDselection::k3sigma;
135+
}
136+
137+
/// function that checks whether the PID selection specified in the vectors is fulfilled
138+
/// \param pidcut Bit-wise container for the PID
139+
/// \param vSpecies Vector with the different selections
140+
/// \return Whether the PID selection specified in the vectors is fulfilled
141+
bool isPIDSelected(aod::femtodreamparticle::cutContainerType const& pidcut, std::vector<int> const& vSpecies, float nSigma, kDetector iDet = kDetector::kTPC)
142+
{
143+
bool pidSelection = true;
144+
kPIDselection kNsigma = getPIDselection(nSigma);
145+
for (auto iSpecies : vSpecies) {
146+
//\todo we also need the possibility to specify whether the bit is true/false ->std>>vector<std::pair<int, int>>
147+
// if (!((pidcut >> it.first) & it.second)) {
148+
int bit_to_check = cfgNspecies * kDetector::kNdetectors * kNsigma + iSpecies * kDetector::kNdetectors + iDet;
149+
if (!(pidcut & (1UL << bit_to_check))) {
150+
pidSelection = false;
151+
}
152+
}
153+
return pidSelection;
154+
};
155+
156+
/// function that checks whether the PID selection specified in the vectors is fulfilled, depending on the momentum TPC or TPC+TOF PID is conducted
157+
/// \param pidcut Bit-wise container for the PID
158+
/// \param mom Momentum of the track
159+
/// \param pidThresh Momentum threshold that separates between TPC and TPC+TOF PID
160+
/// \param vecTPC Vector with the different selections for the TPC PID
161+
/// \param vecComb Vector with the different selections for the TPC+TOF PID
162+
/// \return Whether the PID selection is fulfilled
163+
bool isFullPIDSelected(aod::femtodreamparticle::cutContainerType const& pidCut, float const& momentum, float const& pidThresh, std::vector<int> const& vSpecies, float nSigmaTPC = 3.5, float nSigmaTPCTOF = 3.5)
164+
{
165+
bool pidSelection = true;
166+
if (momentum < pidThresh) {
167+
/// TPC PID only
168+
pidSelection = isPIDSelected(pidCut, vSpecies, nSigmaTPC, kDetector::kTPC);
169+
} else {
170+
/// TPC + TOF PID
171+
pidSelection = isPIDSelected(pidCut, vSpecies, nSigmaTPCTOF, kDetector::kTPCTOF);
172+
}
173+
return pidSelection;
174+
};
175+
176+
/// This function processes the same event and takes care of all the histogramming
177+
/// \todo the trivial loops over the tracks should be factored out since they will be common to all combinations of T-T, T-V0, V0-V0, ...
178+
void processSameEvent(o2::aod::FemtoDreamCollision& col,
179+
o2::aod::FemtoDreamParticles& parts)
180+
{
181+
const int multCol = col.multV0M();
182+
eventHisto.fillQA(col);
183+
/// Histogramming same event
184+
for (auto& part : partsOne) {
185+
if (!isFullPIDSelected(part.pidcut(), part.p(), cfgCutArray->get("PIDthr"), vPIDPartOne, cfgCutArray->get("nSigmaTPC"), cfgCutArray->get("nSigmaTPCTOF"))) {
186+
continue;
187+
}
188+
trackHistoPartOne.fillQA(part);
189+
}
190+
for (auto& part : partsTwo) {
191+
trackHistoPartTwo.fillQA(part);
192+
}
193+
/// Now build the combinations
194+
for (auto& [p1, p2] : combinations(partsOne, partsTwo)) {
195+
if (!isFullPIDSelected(p1.pidcut(), p1.p(), cfgCutArray->get("PIDthr"), vPIDPartOne, cfgCutArray->get("nSigmaTPC"), cfgCutArray->get("nSigmaTPCTOF"))) {
196+
continue;
197+
}
198+
199+
/// close pair rejection
200+
if (ConfIsCPR) {
201+
if (pairCloseRejection.isClosePair(p1, p2, parts)) {
202+
continue;
203+
}
204+
}
205+
206+
// track cleaning
207+
if (!pairCleaner.isCleanPair(p1, p2, parts)) {
208+
continue;
209+
}
210+
sameEventCont.setPair(p1, p2, multCol);
211+
}
212+
}
213+
214+
PROCESS_SWITCH(femtoDreamPairTaskTrackV0, processSameEvent, "Enable processing same event", true);
215+
216+
/// This function processes the mixed event
217+
/// \todo the trivial loops over the collisions and tracks should be factored out since they will be common to all combinations of T-T, T-V0, V0-V0, ...
218+
void processMixedEvent(o2::aod::FemtoDreamCollisions& cols,
219+
o2::aod::Hashes& hashes,
220+
o2::aod::FemtoDreamParticles& parts)
221+
{
222+
cols.bindExternalIndices(&parts);
223+
auto particlesTuple = std::make_tuple(parts);
224+
AnalysisDataProcessorBuilder::GroupSlicer slicer(cols, particlesTuple);
225+
226+
for (auto& [collision1, collision2] : soa::selfCombinations("fBin", ConfNEventsMix, -1, soa::join(hashes, cols), soa::join(hashes, cols))) {
227+
auto it1 = slicer.begin();
228+
auto it2 = slicer.begin();
229+
for (auto& slice : slicer) {
230+
if (slice.groupingElement().index() == collision1.index()) {
231+
it1 = slice;
232+
break;
233+
}
234+
}
235+
for (auto& slice : slicer) {
236+
if (slice.groupingElement().index() == collision2.index()) {
237+
it2 = slice;
238+
break;
239+
}
240+
}
241+
242+
auto particles1 = std::get<aod::FemtoDreamParticles>(it1.associatedTables());
243+
particles1.bindExternalIndices(&cols);
244+
auto particles2 = std::get<aod::FemtoDreamParticles>(it2.associatedTables());
245+
particles2.bindExternalIndices(&cols);
246+
247+
partsOne.bindTable(particles1);
248+
partsTwo.bindTable(particles2);
249+
250+
/// \todo before mixing we should check whether both collisions contain a pair of particles!
251+
/// could work like that, but only if PID is contained within the partitioning!
252+
// auto particlesEvent1 = std::get<aod::FemtoDreamParticles>(it1.associatedTables());
253+
// particlesEvent1.bindExternalIndices(&cols);
254+
// auto particlesEvent2 = std::get<aod::FemtoDreamParticles>(it2.associatedTables());
255+
// particlesEvent2.bindExternalIndices(&cols);
256+
/// for the x-check
257+
// partsOne.bindTable(particlesEvent2);
258+
// auto nPart1Evt2 = partsOne.size();
259+
// partsTwo.bindTable(particlesEvent1);
260+
// auto nPart2Evt1 = partsTwo.size();
261+
/// for actual event mixing
262+
// partsOne.bindTable(particlesEvent1);
263+
// partsTwo.bindTable(particlesEvent2);
264+
// if (partsOne.size() == 0 || nPart2Evt1 == 0 || nPart1Evt2 == 0 || partsTwo.size() == 0 ) continue;
265+
266+
for (auto& [p1, p2] : combinations(partsOne, partsTwo)) {
267+
if (!isFullPIDSelected(p1.pidcut(), p1.p(), cfgCutArray->get("PIDthr"), vPIDPartOne, cfgCutArray->get("nSigmaTPC"), cfgCutArray->get("nSigmaTPCTOF"))) {
268+
continue;
269+
}
270+
if (ConfIsCPR) {
271+
if (pairCloseRejection.isClosePair(p1, p2, parts)) {
272+
continue;
273+
}
274+
}
275+
mixedEventCont.setPair(p1, p2, collision1.multV0M()); // < \todo dirty trick, the multiplicity will be of course within the bin width used for the hashes
276+
}
277+
}
278+
}
279+
280+
PROCESS_SWITCH(femtoDreamPairTaskTrackV0, processMixedEvent, "Enable processing mixed events", true);
281+
};
282+
283+
WorkflowSpec defineDataProcessing(ConfigContext const& cfgc)
284+
{
285+
WorkflowSpec workflow{
286+
adaptAnalysisTask<femtoDreamPairTaskTrackV0>(cfgc),
287+
};
288+
return workflow;
289+
}

0 commit comments

Comments
 (0)