Skip to content

Commit a62b807

Browse files
fmazzascFrancesco Mazzaschi
andauthored
Add task for strangeness tracking efficiency evaluation (AliceO2Group#7953)
Co-authored-by: Francesco Mazzaschi <[email protected]>
1 parent 17da364 commit a62b807

File tree

2 files changed

+265
-0
lines changed

2 files changed

+265
-0
lines changed

PWGLF/Tasks/QC/CMakeLists.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,12 @@ o2physics_add_dpl_workflow(its-tpc-matching-qa
4444
PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore
4545
COMPONENT_NAME Analysis)
4646

47+
o2physics_add_dpl_workflow(strangeness-tracking-qc
48+
SOURCES strangenessTrackingQC.cxx
49+
PUBLIC_LINK_LIBRARIES O2::Framework O2::ReconstructionDataFormats O2Physics::AnalysisCore O2::DetectorsBase
50+
COMPONENT_NAME Analysis)
51+
52+
4753
o2physics_add_dpl_workflow(mc-signal-loss
4854
SOURCES mcSignalLoss.cxx
4955
PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore
Lines changed: 259 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,259 @@
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+
#include "CCDB/BasicCCDBManager.h"
13+
#include "Common/DataModel/Centrality.h"
14+
#include "Common/DataModel/EventSelection.h"
15+
#include "Common/DataModel/PIDResponse.h"
16+
#include "Common/DataModel/TrackSelectionTables.h"
17+
#include "Common/Core/RecoDecay.h"
18+
#include "Common/Core/trackUtilities.h"
19+
#include "DataFormatsParameters/GRPMagField.h"
20+
#include "DataFormatsParameters/GRPObject.h"
21+
#include "DataFormatsTPC/BetheBlochAleph.h"
22+
#include "DCAFitter/DCAFitterN.h"
23+
#include "DetectorsBase/Propagator.h"
24+
#include "Framework/AnalysisTask.h"
25+
#include "Framework/AnalysisDataModel.h"
26+
#include "Framework/ASoA.h"
27+
#include "Framework/ASoAHelpers.h"
28+
#include "Framework/HistogramRegistry.h"
29+
#include "Framework/runDataProcessing.h"
30+
// #include "PWGHF/Core/PDG.h"
31+
#include "PWGLF/DataModel/LFStrangenessTables.h"
32+
#include "ReconstructionDataFormats/DCA.h"
33+
#include "ReconstructionDataFormats/Track.h"
34+
#include "PWGLF/DataModel/LFNonPromptCascadeTables.h"
35+
36+
using namespace o2;
37+
using namespace o2::framework;
38+
using namespace o2::framework::expressions;
39+
40+
namespace
41+
{
42+
43+
};
44+
45+
struct miniCasc {
46+
bool isOmega;
47+
float pt;
48+
float eta;
49+
float phi;
50+
float radius;
51+
float massOmega;
52+
float massXi;
53+
float dcaXYCasc;
54+
float dcaXYTracked;
55+
};
56+
57+
struct strangenessTrackingQC {
58+
59+
using TrackCandidates = soa::Join<aod::TracksIU, aod::TracksExtra, aod::TracksCovIU, aod::pidTPCEl, aod::pidTPCPi, aod::pidTPCKa, aod::pidTPCPr>;
60+
using CollisionCandidates = soa::Join<aod::Collisions, aod::EvSels>;
61+
62+
Configurable<int> setting_materialCorrection{"cfgMaterialCorrection", static_cast<int>(o2::base::Propagator::MatCorrType::USEMatCorrNONE), "Type of material correction"};
63+
64+
Configurable<float> cascsetting_dcaCascDaughters{"casc_setting_dcaV0daughters", 0.1f, "DCA between the V0 daughters"};
65+
Configurable<float> cascsetting_cosPA{"casc_setting_cosPA", 0.995f, "Cosine of the pointing angle of the V0"};
66+
Configurable<float> cascsetting_massWindowOmega{"casc_setting_massWindowOmega", 0.01f, "Mass window for the Omega"};
67+
Configurable<float> cascsetting_massWindowXi{"casc_setting_massWindowXi", 0.01f, "Mass window for the Xi"};
68+
69+
Configurable<std::string> cfgGRPmagPath{"cfgGRPmagPath", "GLO/Config/GRPMagField", "CCDB path of the GRPMagField object"};
70+
Configurable<std::string> cfgGRPpath{"cfgGRPpath", "GLO/GRP/GRP", "Path of the grp file"};
71+
72+
Configurable<float> cfgCutNclusTPC{"cfgCutNclusTPC", 70, "Minimum number of TPC clusters"};
73+
74+
ConfigurableAxis ptBins{"ptBins", {200, -10.f, 10.f}, "Binning for #it{p}_{T} (GeV/#it{c})"};
75+
ConfigurableAxis decayRadBins{"decayRadBins", {100, 0.f, 40.f}, "Binning for decay radius (cm)"};
76+
ConfigurableAxis omegaMassBins{"omegaMassBins", {125, 1.650, 1.700}, "Invariant mass (GeV/#it{c}^{2})"};
77+
ConfigurableAxis xiMassBins{"xiMassBins", {125, 1.296, 1.346}, "Invariant mass (GeV/#it{c}^{2})"};
78+
79+
Service<o2::ccdb::BasicCCDBManager> ccdb;
80+
int mRunNumber = 0;
81+
float bz = 0.f;
82+
o2::vertexing::DCAFitterN<2> m_fitter;
83+
84+
HistogramRegistry registry{
85+
"registry",
86+
{
87+
{"omegaHistFull", "; #it{p}_{T} (GeV/#it{c}); Radius (cm); Mass", {HistType::kTH3F, {{ptBins, decayRadBins, omegaMassBins}}}},
88+
{"xiHistFull", "; #it{p}_{T} (GeV/#it{c}); Radius (cm); Mass", {HistType::kTH3F, {{ptBins, decayRadBins, xiMassBins}}}},
89+
{"xiHistTracked", "; #it{p}_{T} (GeV/#it{c}); Radius (cm); Mass", {HistType::kTH3F, {{ptBins, decayRadBins, xiMassBins}}}},
90+
{"omegaHistTracked", "; #it{p}_{T} (GeV/#it{c}); Radius (cm); Mass", {HistType::kTH3F, {{ptBins, decayRadBins, omegaMassBins}}}},
91+
}};
92+
93+
template <typename T>
94+
float dcaToPV(const std::array<float, 3>& PV, T& trackParCov)
95+
{
96+
gpu::gpustd::array<float, 2> dcaInfo;
97+
o2::base::Propagator::Instance()->propagateToDCABxByBz({PV[0], PV[1], PV[2]}, trackParCov, 2.f, m_fitter.getMatCorrType(), &dcaInfo);
98+
return std::hypot(dcaInfo[0], dcaInfo[1]);
99+
}
100+
101+
template <class TCasc>
102+
bool buildCascade(TCasc const& casc, CollisionCandidates::iterator const& collision, aod::V0s const&, TrackCandidates const&, miniCasc& miniCasc)
103+
{
104+
const auto& v0 = casc.template v0_as<aod::V0s>();
105+
const auto& bachelor = casc.template bachelor_as<TrackCandidates>();
106+
const auto& ptrack = v0.template posTrack_as<TrackCandidates>();
107+
const auto& ntrack = v0.template negTrack_as<TrackCandidates>();
108+
const auto& protonTrack = bachelor.sign() > 0 ? ntrack : ptrack;
109+
const auto& pionTrack = bachelor.sign() > 0 ? ptrack : ntrack;
110+
const auto primaryVertex = getPrimaryVertex(collision);
111+
std::array<float, 3> pvPos = {primaryVertex.getX(), primaryVertex.getY(), primaryVertex.getZ()};
112+
113+
float cascCpa = -1;
114+
float cascDauDCA = -1;
115+
116+
std::array<float, 3> cascMom;
117+
std::array<float, 3> v0Mom;
118+
std::array<float, 3> bachelorMom;
119+
120+
// track propagation
121+
o2::track::TrackParCov trackParCovV0;
122+
o2::track::TrackPar trackParV0;
123+
o2::track::TrackPar trackParBachelor;
124+
o2::track::TrackParCov trackParCovCasc;
125+
if (m_fitter.process(getTrackParCov(pionTrack), getTrackParCov(protonTrack))) {
126+
trackParCovV0 = m_fitter.createParentTrackParCov(0); // V0 track retrieved from p and pi daughters
127+
if (m_fitter.process(trackParCovV0, getTrackParCov(bachelor))) {
128+
trackParV0 = m_fitter.getTrackParamAtPCA(0);
129+
trackParBachelor = m_fitter.getTrackParamAtPCA(1);
130+
trackParV0.getPxPyPzGlo(v0Mom);
131+
trackParBachelor.getPxPyPzGlo(bachelorMom);
132+
trackParCovCasc = m_fitter.createParentTrackParCov();
133+
trackParCovCasc.getPxPyPzGlo(cascMom);
134+
cascCpa = RecoDecay::cpa(pvPos, m_fitter.getPCACandidate(), cascMom);
135+
cascDauDCA = std::sqrt(std::abs(m_fitter.getChi2AtPCACandidate()));
136+
} else {
137+
return false;
138+
}
139+
} else {
140+
return false;
141+
}
142+
143+
if (cascCpa < cascsetting_cosPA || cascCpa == -1) {
144+
return false;
145+
}
146+
147+
if (cascDauDCA > cascsetting_dcaCascDaughters || cascDauDCA == -1) {
148+
return false;
149+
}
150+
151+
miniCasc.pt = std::hypot(cascMom[0], cascMom[1]);
152+
153+
// look if the cascade is in the Xi mass window
154+
std::array<double, 2> masses;
155+
float eV0 = std::sqrt(RecoDecay::p2(v0Mom) + o2::constants::physics::MassLambda0 * o2::constants::physics::MassLambda0);
156+
float eKBach = std::sqrt(RecoDecay::p2(bachelorMom) + o2::constants::physics::MassKPlus * o2::constants::physics::MassKPlus);
157+
float ePiBach = std::sqrt(RecoDecay::p2(bachelorMom) + o2::constants::physics::MassPiPlus * o2::constants::physics::MassPiPlus);
158+
miniCasc.massOmega = std::sqrt((eV0 + eKBach) * (eV0 + eKBach) - RecoDecay::p2(cascMom));
159+
miniCasc.massXi = std::sqrt((eV0 + ePiBach) * (eV0 + ePiBach) - RecoDecay::p2(cascMom));
160+
161+
miniCasc.isOmega = false;
162+
if (TMath::Abs(miniCasc.massXi - constants::physics::MassXiMinus) > 0.005) {
163+
miniCasc.isOmega = true;
164+
}
165+
166+
miniCasc.dcaXYCasc = dcaToPV(pvPos, trackParCovCasc);
167+
auto svPos = m_fitter.getPCACandidate();
168+
miniCasc.radius = std::hypot(svPos[0], svPos[1]);
169+
170+
return true;
171+
}
172+
173+
void initCCDB(aod::BCsWithTimestamps::iterator const& bc)
174+
{
175+
if (mRunNumber == bc.runNumber()) {
176+
return;
177+
}
178+
mRunNumber = bc.runNumber();
179+
auto timestamp = bc.timestamp();
180+
181+
if (o2::parameters::GRPObject* grpo = ccdb->getForTimeStamp<o2::parameters::GRPObject>(cfgGRPpath, timestamp)) {
182+
o2::base::Propagator::initFieldFromGRP(grpo);
183+
bz = grpo->getNominalL3Field();
184+
} else if (o2::parameters::GRPMagField* grpmag = ccdb->getForTimeStamp<o2::parameters::GRPMagField>(cfgGRPmagPath, timestamp)) {
185+
o2::base::Propagator::initFieldFromGRP(grpmag);
186+
bz = std::lround(5.f * grpmag->getL3Current() / 30000.f);
187+
LOG(debug) << "bz = " << bz;
188+
} else {
189+
LOG(fatal) << "Got nullptr from CCDB for path " << cfgGRPmagPath << " of object GRPMagField and " << cfgGRPpath << " of object GRPObject for timestamp " << timestamp;
190+
}
191+
}
192+
193+
void init(InitContext const&)
194+
{
195+
mRunNumber = 0;
196+
bz = 0;
197+
198+
ccdb->setURL("http://alice-ccdb.cern.ch");
199+
ccdb->setCaching(true);
200+
ccdb->setLocalObjectValidityChecking();
201+
ccdb->setFatalWhenNull(false);
202+
// lut = o2::base::MatLayerCylSet::rectifyPtrFromFile(ccdb->get<o2::base::MatLayerCylSet>("GLO/Param/MatLUT"));
203+
204+
m_fitter.setPropagateToPCA(true);
205+
m_fitter.setMaxR(200.);
206+
m_fitter.setMinParamChange(1e-3);
207+
m_fitter.setMinRelChi2Change(0.9);
208+
m_fitter.setMaxDZIni(4);
209+
m_fitter.setMaxDXYIni(4);
210+
m_fitter.setMaxChi2(1e9);
211+
m_fitter.setUseAbsDCA(true);
212+
m_fitter.setWeightedFinalPCA(false);
213+
int mat{static_cast<int>(setting_materialCorrection)};
214+
m_fitter.setMatCorrType(static_cast<o2::base::Propagator::MatCorrType>(mat));
215+
}
216+
217+
void process(CollisionCandidates const& collisions, aod::AssignedTrackedCascades const& trackedCascades, aod::Cascades const& cascades, aod::V0s const& v0s, TrackCandidates const& tracks, aod::BCsWithTimestamps const&)
218+
{
219+
for (const auto& trackedCascade : trackedCascades) {
220+
miniCasc miniCasc;
221+
const auto& casc = trackedCascade.cascade();
222+
auto collision = trackedCascade.collision_as<CollisionCandidates>();
223+
if (buildCascade(casc, collision, v0s, tracks, miniCasc)) {
224+
225+
// compute the dca of the tracked cascade
226+
const auto& track = trackedCascade.track_as<TrackCandidates>();
227+
auto trackCovTrk = getTrackParCov(track);
228+
229+
auto pvPos = getPrimaryVertex(collision);
230+
auto pvPosArr = std::array<float, 3>{pvPos.getX(), pvPos.getY(), pvPos.getZ()};
231+
miniCasc.dcaXYTracked = dcaToPV(pvPosArr, trackCovTrk);
232+
// fill the histograms
233+
if (miniCasc.isOmega) {
234+
registry.fill(HIST("omegaHistTracked"), miniCasc.pt, miniCasc.radius, miniCasc.massOmega);
235+
} else {
236+
registry.fill(HIST("xiHistTracked"), miniCasc.pt, miniCasc.radius, miniCasc.massXi);
237+
}
238+
}
239+
}
240+
241+
for (auto& cascade : cascades) {
242+
miniCasc miniCasc;
243+
auto collision = cascade.collision_as<CollisionCandidates>();
244+
if (buildCascade(cascade, collision, v0s, tracks, miniCasc)) {
245+
if (miniCasc.isOmega) {
246+
registry.fill(HIST("omegaHistFull"), miniCasc.pt, miniCasc.radius, miniCasc.massOmega);
247+
} else {
248+
registry.fill(HIST("xiHistFull"), miniCasc.pt, miniCasc.radius, miniCasc.massXi);
249+
}
250+
}
251+
}
252+
}
253+
};
254+
255+
WorkflowSpec defineDataProcessing(ConfigContext const& cfgc)
256+
{
257+
return WorkflowSpec{
258+
adaptAnalysisTask<strangenessTrackingQC>(cfgc)};
259+
}

0 commit comments

Comments
 (0)