Skip to content

Commit 5b2013e

Browse files
committed
A3: add trkpid
1 parent a93e92c commit 5b2013e

File tree

2 files changed

+263
-0
lines changed

2 files changed

+263
-0
lines changed

ALICE3/DataModel/OTFPIDTrk.h

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
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+
///
13+
/// \file OTFPIDTrk.h
14+
/// \author Berkin Ulukutlu TUM
15+
/// \author Henrik Fribert TUM
16+
/// \author Nicolò Jacazio Università del Piemonte Orientale
17+
/// \since May 22, 2025
18+
/// \brief Set of tables for the ALICE3 Trk PID information
19+
///
20+
21+
#ifndef ALICE3_DATAMODEL_OTFPIDTRK_H_
22+
#define ALICE3_DATAMODEL_OTFPIDTRK_H_
23+
24+
// O2 includes
25+
#include "Framework/AnalysisDataModel.h"
26+
27+
namespace o2::aod
28+
{
29+
namespace upgrade::trk
30+
{
31+
32+
DECLARE_SOA_COLUMN(TimeOverThresholdBarrel, timeOverThresholdBarrel, float); //! Time over threshold for the barrel layers
33+
DECLARE_SOA_COLUMN(ClusterSizeBarrel, clusterSizeBarrel, float); //! Cluster size for the barrel layers
34+
DECLARE_SOA_COLUMN(TimeOverThresholdForward, timeOverThresholdForward, float); //! Time over threshold for the Forward layers
35+
DECLARE_SOA_COLUMN(ClusterSizeForward, clusterSizeForward, float); //! Cluster size for the barrel layers
36+
37+
DECLARE_SOA_COLUMN(NSigmaTrkEl, nSigmaEl, float); //! NSigma electron from the tracker layers
38+
DECLARE_SOA_COLUMN(NSigmaTrkMu, nSigmaMu, float); //! NSigma muon from the tracker layers
39+
DECLARE_SOA_COLUMN(NSigmaTrkPi, nSigmaPi, float); //! NSigma pion from the tracker layers
40+
DECLARE_SOA_COLUMN(NSigmaTrkKa, nSigmaKa, float); //! NSigma kaon from the tracker layers
41+
DECLARE_SOA_COLUMN(NSigmaTrkPr, nSigmaPr, float); //! NSigma proton from the tracker layers
42+
43+
DECLARE_SOA_DYNAMIC_COLUMN(NSigmaTrk, nSigmaTrk, //! General function to get the nSigma for the tracker layers
44+
[](const float el,
45+
const float mu,
46+
const float pi,
47+
const float ka,
48+
const float pr,
49+
const int id) -> float {
50+
switch (std::abs(id)) {
51+
case 0:
52+
return el;
53+
case 1:
54+
return mu;
55+
case 2:
56+
return pi;
57+
case 3:
58+
return ka;
59+
case 4:
60+
return pr;
61+
default:
62+
LOG(fatal) << "Unrecognized PDG code for InnerTOF";
63+
return 999.f;
64+
}
65+
});
66+
67+
} // namespace upgrade::trk
68+
69+
DECLARE_SOA_TABLE(UpgradeTrkPidSignals, "AOD", "UPGRADETRKSIG",
70+
upgrade::trk::TimeOverThresholdBarrel,
71+
upgrade::trk::ClusterSizeBarrel);
72+
73+
DECLARE_SOA_TABLE(UpgradeTrkPids, "AOD", "UPGRADETRKPID",
74+
upgrade::trk::NSigmaTrkEl,
75+
upgrade::trk::NSigmaTrkMu,
76+
upgrade::trk::NSigmaTrkPi,
77+
upgrade::trk::NSigmaTrkKa,
78+
upgrade::trk::NSigmaTrkPr,
79+
upgrade::trk::NSigmaTrk<upgrade::trk::NSigmaTrkEl,
80+
upgrade::trk::NSigmaTrkMu,
81+
upgrade::trk::NSigmaTrkPi,
82+
upgrade::trk::NSigmaTrkKa,
83+
upgrade::trk::NSigmaTrkPr>);
84+
85+
using UpgradeTrkPidSignal = UpgradeTrkPidSignals::iterator;
86+
using UpgradeTrkPid = UpgradeTrkPids::iterator;
87+
88+
} // namespace o2::aod
89+
90+
#endif // ALICE3_DATAMODEL_OTFPIDTRK_H_
Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
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 onTheFlyTrackerPid.cxx
13+
///
14+
/// \brief This task produces the PID information that can be obtained from the tracker layers (i.e. cluster size and ToT).
15+
/// It currently contemplates 5 particle types: electrons, muons, pions, kaons and protons.
16+
///
17+
/// \author Berkin Ulukutlu TUM
18+
/// \author Henrik Fribert TUM
19+
/// \author Nicolò Jacazio Università del Piemonte Orientale
20+
/// \since May 22, 2025
21+
///
22+
23+
#include <utility>
24+
#include <map>
25+
#include <string>
26+
#include <vector>
27+
28+
#include "Framework/AnalysisDataModel.h"
29+
#include "Framework/AnalysisTask.h"
30+
#include "Framework/runDataProcessing.h"
31+
#include "Framework/RunningWorkflowInfo.h"
32+
#include "Framework/HistogramRegistry.h"
33+
#include "Framework/O2DatabasePDGPlugin.h"
34+
#include "Framework/ASoAHelpers.h"
35+
#include "Common/DataModel/TrackSelectionTables.h"
36+
#include "Common/Core/trackUtilities.h"
37+
#include "ALICE3/Core/TrackUtilities.h"
38+
#include "ReconstructionDataFormats/DCA.h"
39+
#include "DetectorsBase/Propagator.h"
40+
#include "DetectorsBase/GeometryManager.h"
41+
#include "CommonUtils/NameConf.h"
42+
#include "CCDB/CcdbApi.h"
43+
#include "CCDB/BasicCCDBManager.h"
44+
#include "DataFormatsParameters/GRPMagField.h"
45+
#include "DataFormatsCalibration/MeanVertexObject.h"
46+
#include "CommonConstants/GeomConstants.h"
47+
#include "CommonConstants/PhysicsConstants.h"
48+
#include "TRandom3.h"
49+
#include "TF1.h"
50+
#include "TH2F.h"
51+
#include "TVector3.h"
52+
#include "TString.h"
53+
#include "ALICE3/DataModel/OTFRICH.h"
54+
#include "DetectorsVertexing/HelixHelper.h"
55+
#include "TableHelper.h"
56+
#include "ALICE3/Core/DelphesO2TrackSmearer.h"
57+
#include "ALICE3/DataModel/OTFPIDTrk.h"
58+
59+
using namespace o2;
60+
using namespace o2::framework;
61+
62+
struct OnTheFlyTrackerPid {
63+
Produces<aod::UpgradeTrkPidSignals> tableUpgradeTrkPidSignals;
64+
Produces<aod::UpgradeTrkPids> tableUpgradeTrkPids;
65+
66+
// necessary for particle charges
67+
Service<o2::framework::O2DatabasePDG> pdg;
68+
69+
static constexpr int kMaxBarrelLayers = 8;
70+
static constexpr int kMaxForwardLayers = 9;
71+
72+
struct : ConfigurableGroup {
73+
Configurable<std::string> efficiencyFormula{"efficiencyFormula", "1.0/(1.0+exp(-(x-0.01)/0.2))", "ROOT TF1 formula for efficiency"};
74+
Configurable<std::string> landauFormula{"landauFormula", "TMath::Landau(x, 1, 1, true)", "ROOT TF1 formula for Landau distribution (e.g. ToT response)"};
75+
Configurable<int> averageMethod{"averageMethod", 0, "Method to average the ToT and cluster size. 0: truncated mean"};
76+
} simConfig;
77+
78+
TF1* mEfficiency = nullptr;
79+
static constexpr int kEtaBins = 50;
80+
static constexpr float kEtaMin = -2.5;
81+
static constexpr float kEtaMax = 2.5;
82+
static constexpr int kPtBins = 200;
83+
static constexpr float kPtMin = 0.0;
84+
static constexpr float kPtMax = 20.0;
85+
86+
std::array<std::array<TF1*, kPtBins>, kEtaBins> mElossPi;
87+
88+
void init(o2::framework::InitContext&)
89+
{
90+
91+
for (int i = 0; i < kEtaBins; i++) {
92+
for (int j = 0; j < kPtBins; j++) {
93+
mElossPi[i][j] = new TF1(Form("mElossPi_%d_%d", i, j), simConfig.landauFormula.value.c_str(), 0, 20);
94+
}
95+
}
96+
mEfficiency = new TF1("mEfficiency", simConfig.efficiencyFormula.value.c_str(), 0, 20);
97+
}
98+
99+
void process(soa::Join<aod::Collisions, aod::McCollisionLabels>::iterator const&,
100+
soa::Join<aod::Tracks, aod::TracksCov, aod::McTrackLabels> const& tracks,
101+
aod::McParticles const&,
102+
aod::McCollisions const&)
103+
{
104+
std::array<float, kMaxBarrelLayers> timeOverThresholdBarrel;
105+
std::array<float, kMaxBarrelLayers> clusterSizeBarrel;
106+
// std::array<float, kMaxForwardLayers> timeOverThresholdForward;
107+
// std::array<float, kMaxForwardLayers> clusterSizeForward;
108+
109+
auto noSignalTrack = []() {
110+
tableUpgradeTrkPidSignals(0.f, 0.f); // no PID information
111+
tableUpgradeTrkPids(0.f, 0.f, 0.f, 0.f, 0.f); // no PID information
112+
};
113+
114+
for (const auto& track : tracks) {
115+
if (!track.has_mcParticle()) {
116+
noSignalTrack();
117+
continue;
118+
}
119+
const auto& mcParticle = track.mcParticle();
120+
const auto& pdgInfo = pdg->GetParticle(mcParticle.pdgCode());
121+
if (!pdgInfo) {
122+
LOG(warning) << "PDG code " << mcParticle.pdgCode() << " not found in the database";
123+
noSignalTrack();
124+
continue;
125+
}
126+
const float pt = mcParticle.pt();
127+
const float eta = mcParticle.eta();
128+
129+
const int binnedPt = static_cast<int>((pt - kPtMin) / kPtBins);
130+
const int binnedEta = static_cast<int>((eta - kEtaMin) / kEtaBins);
131+
if (binnedPt < 0 || binnedPt >= kPtBins || binnedEta < 0 || binnedEta >= kEtaBins) {
132+
noSignalTrack();
133+
continue;
134+
}
135+
for (int i = 0; i < kMaxBarrelLayers; i++) {
136+
timeOverThresholdBarrel[i] = -1;
137+
clusterSizeBarrel[i] = -1;
138+
139+
// Check if layer is efficient
140+
if (mEfficiency->Eval(pt) > gRandom->Uniform(0, 1)) {
141+
timeOverThresholdBarrel[i] = mElossPi[binnedEta][binnedPt]->GetRandom(); // Simulate ToT
142+
clusterSizeBarrel[i] = mElossPi[binnedEta][binnedPt]->GetRandom(); // Simulate cluster size
143+
}
144+
}
145+
146+
// Now we do the average
147+
switch (simConfig.averageMethod) {
148+
case 0: { // truncated mean
149+
float meanToT = 0;
150+
float meanClusterSize = 0;
151+
// Order them by ToT
152+
std::sort(timeOverThresholdBarrel.begin(), timeOverThresholdBarrel.end());
153+
std::sort(clusterSizeBarrel.begin(), clusterSizeBarrel.end());
154+
// Take the mean of the first 5 values
155+
for (int i = 0; i < 5; i++) {
156+
meanToT += timeOverThresholdBarrel[i];
157+
meanClusterSize += clusterSizeBarrel[i];
158+
}
159+
meanToT /= 5;
160+
meanClusterSize /= 5;
161+
// Fill the table
162+
tableUpgradeTrkPidSignals(meanToT, meanClusterSize);
163+
} break;
164+
165+
default:
166+
LOG(fatal) << "Unknown average method " << simConfig.averageMethod;
167+
break;
168+
}
169+
}
170+
}
171+
};
172+
173+
WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { return WorkflowSpec{adaptAnalysisTask<OnTheFlyTrackerPid>(cfgc)}; }

0 commit comments

Comments
 (0)