|
14 | 14 | /// \author Arkaprabha Saha <arkaprabha.saha@cern.ch> |
15 | 15 |
|
16 | 16 | #include "Common/Core/PID/TPCPIDResponse.h" |
| 17 | +#include "Common/Core/RecoDecay.h" |
17 | 18 | #include "Common/Core/TrackSelection.h" |
18 | 19 | #include "Common/Core/TrackSelectionDefaults.h" |
19 | 20 | #include "Common/DataModel/Centrality.h" |
20 | 21 | #include "Common/DataModel/EventSelection.h" |
21 | 22 | #include "Common/DataModel/PIDResponseTOF.h" |
22 | 23 | #include "Common/DataModel/TrackSelectionTables.h" |
23 | | - |
24 | 24 | #include "MathUtils/BetheBlochAleph.h" |
25 | 25 | #include "Framework/AnalysisDataModel.h" |
26 | 26 | #include "Framework/AnalysisTask.h" |
27 | 27 | #include "Framework/HistogramRegistry.h" |
28 | 28 | #include "Framework/runDataProcessing.h" |
29 | | - |
| 29 | +#include <TMCProcess.h> |
30 | 30 | #include <TParameter.h> |
31 | | - |
32 | 31 | #include <cmath> |
33 | 32 | #include <string> |
34 | 33 | #include <vector> |
35 | 34 |
|
36 | 35 | using namespace o2; |
37 | 36 | using namespace o2::framework; |
| 37 | +using namespace o2::framework::expressions; |
| 38 | +using namespace o2::constants::physics; |
| 39 | + |
38 | 40 | using CollisionWithEvSel = soa::Join<aod::Collisions, aod::EvSels, aod::CentFT0Cs>; |
39 | 41 | using TotalTracks = soa::Join<aod::Tracks, aod::TracksExtra, aod::TracksDCA, aod::pidTOFDe>; |
| 42 | +using CollisionMC = soa::Join<aod::Collisions, aod::EvSels, aod::CentFT0Cs, aod::McCollisionLabels>; |
| 43 | +using TracksMC = soa::Join<aod::Tracks, aod::TracksExtra, aod::TracksDCA, aod::pidTOFDe, aod::McTrackLabels>; |
40 | 44 |
|
41 | 45 | namespace |
42 | 46 | { |
43 | | -static const std::vector<std::string> particleName{"d"}; |
| 47 | +static const int kPdgCodeHe3 = 1000020030; |
| 48 | +static const float kMaxEta = 0.8f; |
| 49 | +static const float kMaxGenRapidity = 0.5f; |
| 50 | +static const float kMaxVertexZ = 10.f; |
| 51 | +static const int kMinTpcCrossedRows = 70; |
44 | 52 | static const double kBetheBlochDefault[6]{-1.e32, -1.e32, -1.e32, -1.e32, -1.e32, -1.e32}; |
45 | | -static const std::vector<std::string> betheBlochParNames{"p0", "p1", "p2", "p3", "p4", "resolution"}; |
46 | | -static const float maxEtaCut = 0.8f; |
47 | | -static const int minTpcCrossedRowsCut = 70; |
48 | | -static const float maxVertexZCut = 10.f; |
49 | | -} // namespace |
| 53 | +static const std::vector<std::string> kParamNamesBB{"p0", "p1", "p2", "p3", "p4", "resolution"}; |
| 54 | +static const std::vector<std::string> kParticleNamesBB{"He3"}; |
| 55 | +} |
50 | 56 |
|
51 | 57 | struct AntiNucleiTask { |
52 | | - // Histogram registry: for holding histograms |
53 | | - HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject}; |
54 | | - |
55 | | - // Configurable track cuts |
56 | | - Configurable<float> trackNclusTPCcut{"trackNclusTPCcut", 70.0f, "min number of TPC clusters"}; |
57 | | - Configurable<float> trackNclusITScut{"trackNclusITScut", 4.0f, "min number of ITS clusters"}; |
58 | | - Configurable<float> maxChi2TPC{"maxChi2TPC", 4.0f, "max chi2 per cluster TPC"}; |
59 | | - Configurable<float> minChi2TPC{"minChi2TPC", 0.0f, "min chi2 per cluster TPC"}; |
60 | | - Configurable<float> chi2ITS{"chi2ITS", 36.0f, "max chi2 per cluster ITS"}; |
61 | | - Configurable<float> trackDCAz{"trackDCAz", 0.1f, "maxDCAz"}; |
62 | | - Configurable<float> trackDCAxy{"trackDCAxy", 0.1f, "maxDCAxy"}; |
63 | | - Configurable<float> tpcNSigmaCut{"tpcNSigmaCut", 3.0f, "tpcNSigmaCut"}; |
64 | | - Configurable<LabeledArray<double>> cfgBetheBlochParams{"cfgBetheBlochParams", {kBetheBlochDefault, 1, 6, particleName, betheBlochParNames}, "TPC Bethe-Bloch parameterisation for deuteron"}; |
| 58 | + HistogramRegistry histo{"histos", {}, OutputObjHandlingPolicy::AnalysisObject}; |
| 59 | + |
| 60 | + Configurable<float> mMinClsTPC{"minClsTPC", 70.0f, ""}; |
| 61 | + Configurable<float> mMinClsITS{"minClsITS", 4.0f, ""}; |
| 62 | + Configurable<float> mMaxChi2TPC{"maxChi2TPC", 4.0f, ""}; |
| 63 | + Configurable<float> mMinChi2TPC{"minChi2TPC", 0.0f, ""}; |
| 64 | + Configurable<float> mMaxChi2ITS{"maxChi2ITS", 36.0f, ""}; |
| 65 | + Configurable<float> mMaxDCAZ{"maxDCAZ", 0.02f, ""}; |
| 66 | + Configurable<float> mMaxDCAXY{"maxDCAXY", 0.02f, ""}; |
| 67 | + Configurable<float> mMaxNsigmaTPC{"maxNsigmaTPC", 3.0f, ""}; |
| 68 | + Configurable<LabeledArray<double>> mBetheBlochParams{"betheBlochParams", {kBetheBlochDefault, 1, 6, kParticleNamesBB, kParamNamesBB}, ""}; |
65 | 69 |
|
66 | 70 | void init(InitContext const&) |
67 | | - { // Defining the Histogram Axes |
68 | | - ConfigurableAxis etaAxis{"etaAxis", {16, -0.8, +0.8}, "#eta"}; |
69 | | - ConfigurableAxis phiAxis{"phiAxis", {70, 0.f, 7.f}, "#phi"}; |
70 | | - ConfigurableAxis zVtxAxis{"zVtxAxis", {100, -20.f, 20.f}, "Primary Vertex z (cm)"}; |
71 | | - ConfigurableAxis nSigmaAxis{"nSigmaAxis", {50, -5.f, 5.f}, "N_{#sigma}"}; |
72 | | - ConfigurableAxis ptAxis{"ptAxis", {200, -10.0f, 10.0f}, "p_{T} (GeV/c)"}; |
73 | | - ConfigurableAxis centAxis{"centAxis", {100, 0, 100.0f}, "Centrality"}; |
74 | | - ConfigurableAxis momAxis{"momAxis", {5.e2, 0.f, 5.f}, "momentum axis binning"}; |
75 | | - ConfigurableAxis tpcAxis{"tpcAxis", {4.e2, 0.f, 4.e3f}, "tpc signal axis binning"}; |
76 | | - |
77 | | - // Creating histograms |
78 | | - histos.add("RawzVtx", "RawzVtx", kTH1F, {{zVtxAxis, "Primary Vertex z (cm)"}}); |
79 | | - histos.add("zVtx", "zVtx", kTH1F, {{zVtxAxis, "Primary Vertex z (cm)"}}); |
80 | | - histos.add("RawEta", "RawEta", kTH1F, {{etaAxis, "#eta"}}); |
81 | | - histos.add("Eta", "Eta", kTH1F, {{etaAxis, "#eta"}}); |
82 | | - histos.add("RawPhi", "RawPhi", kTH1F, {{phiAxis, "#phi (rad)"}}); |
83 | | - histos.add("Phi", "Phi", kTH1F, {{phiAxis, "#phi (rad)"}}); |
84 | | - histos.add("RawPt", "RawPt", kTH1F, {{ptAxis, "#it{p}_{T} (GeV/#it{c})"}}); |
85 | | - histos.add("Pt", "Pt", kTH1F, {{ptAxis, "#it{p}_{T} (GeV/#it{c})"}}); |
86 | | - histos.add("TpcSignal", "TpcSignal", kTH2F, {{momAxis, "#it{p}_{TPC} (GeV/#it{c})"}, {tpcAxis, "d#it{E}/d#it{x}_{TPC}"}}); |
87 | | - histos.add("RawtpcNSigma", "RawtpcNSigma", kTH3F, {{centAxis, "Centrality"}, {ptAxis, "#it{p}_{T} (GeV/#it{c})"}, {nSigmaAxis, "N_{#sigma}"}}); |
88 | | - histos.add("tpcNSigma", "tpcNSigma", kTH3F, {{centAxis, "Centrality"}, {ptAxis, "#it{p}_{T} (GeV/#it{c})"}, {nSigmaAxis, "N_{#sigma}"}}); |
89 | | - histos.add("RawtofNSigma", "RawtofNSigma", kTH3F, {{centAxis, "Centrality"}, {ptAxis, "#it{p}_{T} (GeV/#it{c})"}, {nSigmaAxis, "N_{#sigma}"}}); |
90 | | - histos.add("tofNSigma", "tofNSigma", kTH3F, {{centAxis, "Centrality"}, {ptAxis, "#it{p}_{T} (GeV/#it{c})"}, {nSigmaAxis, "N_{#sigma}"}}); |
| 71 | + { |
| 72 | + ConfigurableAxis axisEta{"eta", {16, -0.8, +0.8}, "#eta"}; |
| 73 | + ConfigurableAxis axisPhi{"phi", {70, 0.f, 7.f}, "#phi (rad)"}; |
| 74 | + ConfigurableAxis axisZVtx{"zVtx", {100, -20.f, 20.f}, "Vertex z (cm)"}; |
| 75 | + ConfigurableAxis axisNSigma{"nSigma", {50, -5.f, 5.f}, "n#sigma"}; |
| 76 | + ConfigurableAxis axisPt{"pt", {200, -10.0f, 10.0f}, "#it{p}_{T} (GeV/#it{c})"}; |
| 77 | + ConfigurableAxis axisMomTPC{"momTPC", {5.e2, 0.f, 5.f}, "#it{p}_{TPC} (GeV/#it{c})"}; |
| 78 | + ConfigurableAxis axisSignalTPC{"signalTPC", {4.e2, 0.f, 4.e3f}, "d#it{E}/d#it{x}_{TPC} (a.u.)"}; |
| 79 | + ConfigurableAxis axisCent{"centAxis", {100, 0, 100.0f}, "Centrality"}; |
| 80 | + |
| 81 | + histo.add("ZVtx_Raw", "Raw Z-vertex", kTH1F, {{axisZVtx}}); |
| 82 | + histo.add("ZVtx", "Z-vertex", kTH1F, {{axisZVtx}}); |
| 83 | + histo.add("Eta_Raw", "Raw Eta", kTH1F, {{axisEta}}); |
| 84 | + histo.add("Eta", "Eta", kTH1F, {{axisEta}}); |
| 85 | + histo.add("Phi_Raw", "Raw Phi", kTH1F, {{axisPhi}}); |
| 86 | + histo.add("Phi", "Phi", kTH1F, {{axisPhi}}); |
| 87 | + histo.add("Pt_Raw", "Raw Pt", kTH1F, {{axisPt}}); |
| 88 | + histo.add("Pt", "Pt", kTH1F, {{axisPt}}); |
| 89 | + histo.add("TPCSignal", "TPC dEdx vs Momentum", kTH2F, {{axisMomTPC}, {axisSignalTPC}}); |
| 90 | + histo.add("NSigmaTPC_Raw", "Raw TPC nSigma", kTH3F, {{axisCent}, {axisPt}, {axisNSigma}}); |
| 91 | + histo.add("NSigmaTOF_Raw", "Raw TOF nSigma", kTH3F, {{axisCent}, {axisPt}, {axisNSigma}}); |
| 92 | + histo.add("NSigmaTPC", "TPC nSigma", kTH3F, {{axisCent}, {axisPt}, {axisNSigma}}); |
| 93 | + histo.add("NSigmaTOF", "TOF nSigma", kTH3F, {{axisCent}, {axisPt}, {axisNSigma}}); |
| 94 | + histo.add("GenPt", "Generated He3 (|y|<0.5)", kTH1F, {{axisPt}}); |
| 95 | + histo.add("RecPt", "Reconstructed He3 (|#eta|<0.8)", kTH1F, {{axisPt}}); |
91 | 96 | } |
92 | 97 |
|
93 | | - // Function to apply track cuts |
94 | 98 | template <typename T> |
95 | | - bool isGoodTrack(const T& track) |
| 99 | + bool passTrackSelection(const T& track) |
96 | 100 | { |
97 | | - if (track.eta() > maxEtaCut) |
98 | | - return false; |
99 | | - if (track.tpcNClsFound() < trackNclusTPCcut) |
100 | | - return false; |
101 | | - if (track.tpcNClsCrossedRows() < minTpcCrossedRowsCut) |
102 | | - return false; |
103 | | - if (track.itsNCls() < trackNclusITScut) |
104 | | - return false; |
105 | | - if (track.tpcChi2NCl() > maxChi2TPC) |
106 | | - return false; |
107 | | - if (track.tpcChi2NCl() < minChi2TPC) |
108 | | - return false; |
109 | | - if (track.itsChi2NCl() > chi2ITS) |
110 | | - return false; |
111 | | - if (std::abs(track.dcaXY()) > trackDCAxy) |
112 | | - return false; |
113 | | - if (std::abs(track.dcaZ()) > trackDCAz) |
114 | | - return false; |
115 | | - |
| 101 | + if (std::abs(track.eta()) > kMaxEta) return false; |
| 102 | + if (track.tpcNClsFound() < mMinClsTPC) return false; |
| 103 | + if (track.tpcNClsCrossedRows() < kMinTpcCrossedRows) return false; |
| 104 | + if (track.itsNCls() < mMinClsITS) return false; |
| 105 | + if (track.tpcChi2NCl() > mMaxChi2TPC || track.tpcChi2NCl() < mMinChi2TPC) return false; |
| 106 | + if (track.itsChi2NCl() > mMaxChi2ITS) return false; |
| 107 | + if (std::abs(track.dcaXY()) > mMaxDCAXY || std::abs(track.dcaZ()) > mMaxDCAZ) return false; |
116 | 108 | return true; |
117 | 109 | } |
118 | 110 |
|
119 | | - // The process function |
| 111 | + static float getSignedPtMC(auto const& particle) |
| 112 | + { |
| 113 | + return (particle.pdgCode() > 0) ? particle.pt() : -particle.pt(); |
| 114 | + } |
| 115 | + |
| 116 | + static bool isPrimaryHe3(auto const& particle) |
| 117 | + { |
| 118 | + return std::abs(particle.pdgCode()) == kPdgCodeHe3 && particle.isPhysicalPrimary(); |
| 119 | + } |
| 120 | + |
120 | 121 | void process(CollisionWithEvSel::iterator const& collision, TotalTracks const& tracks) |
121 | 122 | { |
122 | | - // Event Selection |
123 | | - if (std::abs(collision.posZ()) > maxVertexZCut) { |
124 | | - return; |
125 | | - } |
| 123 | + if (std::abs(collision.posZ()) > kMaxVertexZ) return; |
| 124 | + histo.fill(HIST("ZVtx_Raw"), collision.posZ()); |
126 | 125 |
|
127 | | - // Filling the z-vertex histogram before the event selection cuts. |
128 | | - histos.fill(HIST("RawzVtx"), collision.posZ()); |
| 126 | + if (!collision.sel8()) return; |
| 127 | + histo.fill(HIST("ZVtx"), collision.posZ()); |
129 | 128 |
|
130 | | - // Applying the built-in O2 event selection (sel8). |
131 | | - if (!collision.sel8()) { |
132 | | - return; |
| 129 | + for (const auto& track : tracks) { |
| 130 | + double expectedSignal = {common::BetheBlochAleph( |
| 131 | + static_cast<double>(track.tpcInnerParam()), |
| 132 | + mBetheBlochParams->get("p0"), mBetheBlochParams->get("p1"), |
| 133 | + mBetheBlochParams->get("p2"), mBetheBlochParams->get("p3"), |
| 134 | + mBetheBlochParams->get("p4"))}; |
| 135 | + |
| 136 | + float nSigmaTPC = static_cast<float>((track.tpcSignal() - expectedSignal) / (expectedSignal * mBetheBlochParams->get("resolution"))); |
| 137 | + float signedPt = (track.sign() > 0) ? 2 * track.pt() : -2 * track.pt(); |
| 138 | + |
| 139 | + histo.fill(HIST("Eta_Raw"), track.eta()); |
| 140 | + histo.fill(HIST("Phi_Raw"), track.phi()); |
| 141 | + histo.fill(HIST("Pt_Raw"), signedPt); |
| 142 | + histo.fill(HIST("NSigmaTPC_Raw"), collision.centFT0C(), signedPt, nSigmaTPC); |
| 143 | + histo.fill(HIST("NSigmaTOF_Raw"), collision.centFT0C(), signedPt, track.tofNSigmaDe()); |
| 144 | + |
| 145 | + if (passTrackSelection(track)) { |
| 146 | + histo.fill(HIST("Eta"), track.eta()); |
| 147 | + histo.fill(HIST("Phi"), track.phi()); |
| 148 | + histo.fill(HIST("Pt"), signedPt); |
| 149 | + histo.fill(HIST("NSigmaTPC"), collision.centFT0C(), signedPt, nSigmaTPC); |
| 150 | + histo.fill(HIST("TPCSignal"), track.tpcInnerParam(), track.tpcSignal()); |
| 151 | + |
| 152 | + if (std::abs(nSigmaTPC) < mMaxNsigmaTPC) { |
| 153 | + histo.fill(HIST("NSigmaTOF"), collision.centFT0C(), signedPt, track.tofNSigmaDe()); |
| 154 | + } |
| 155 | + } |
133 | 156 | } |
| 157 | + } |
134 | 158 |
|
135 | | - // Filling the z-vertex histogram after the event selection cuts. |
136 | | - histos.fill(HIST("zVtx"), collision.posZ()); |
| 159 | + void processMC(CollisionMC const& collisions, aod::McCollisions const&, TracksMC const& tracks, aod::McParticles const& particlesMC) |
| 160 | + { |
| 161 | + for (const auto& collision : collisions) { |
| 162 | + if (std::abs(collision.posZ()) > kMaxVertexZ || !collision.sel8()) continue; |
| 163 | + |
| 164 | + for (const auto& particle : particlesMC) { |
| 165 | + if (particle.mcCollisionId() == collision.mcCollisionId() && isPrimaryHe3(particle)) { |
| 166 | + if (std::abs(particle.y()) < kMaxGenRapidity) { |
| 167 | + histo.fill(HIST("GenPt"), getSignedPtMC(particle)); |
| 168 | + } |
| 169 | + } |
| 170 | + } |
137 | 171 |
|
138 | | - // Track Selection |
139 | | - for (const auto& track : tracks) { |
| 172 | + for (const auto& track : tracks) { |
| 173 | + if (track.collisionId() != collision.index() || !passTrackSelection(track) || track.mcParticleId() == -1) continue; |
140 | 174 |
|
141 | | - double expBethe{common::BetheBlochAleph(static_cast<double>(track.tpcInnerParam()), cfgBetheBlochParams->get("p0"), cfgBetheBlochParams->get("p1"), cfgBetheBlochParams->get("p2"), cfgBetheBlochParams->get("p3"), cfgBetheBlochParams->get("p4"))}; |
142 | | - double expSigma{expBethe * cfgBetheBlochParams->get("resolution")}; |
143 | | - float tpcNSigma = static_cast<float>((track.tpcSignal() - expBethe) / expSigma); |
144 | | - |
145 | | - float pt = track.sign() > 0 ? 2 * track.pt() : -2 * track.pt(); |
146 | | - // Filling histograms with track data before applying any cuts. |
147 | | - histos.fill(HIST("RawEta"), track.eta()); |
148 | | - histos.fill(HIST("RawPhi"), track.phi()); |
149 | | - histos.fill(HIST("RawPt"), pt); |
150 | | - histos.fill(HIST("RawtpcNSigma"), collision.centFT0C(), pt, tpcNSigma); |
151 | | - histos.fill(HIST("RawtofNSigma"), collision.centFT0C(), pt, track.tofNSigmaDe()); |
152 | | - |
153 | | - // If the track is good, fill the "after cuts" histograms. |
154 | | - if (isGoodTrack(track)) { |
155 | | - histos.fill(HIST("Eta"), track.eta()); |
156 | | - histos.fill(HIST("Phi"), track.phi()); |
157 | | - histos.fill(HIST("Pt"), pt); |
158 | | - histos.fill(HIST("tpcNSigma"), collision.centFT0C(), pt, tpcNSigma); |
159 | | - histos.fill(HIST("TpcSignal"), track.tpcInnerParam(), track.tpcSignal()); |
160 | | - |
161 | | - if (std::abs(tpcNSigma) < tpcNSigmaCut) { |
162 | | - histos.fill(HIST("tofNSigma"), collision.centFT0C(), pt, track.tofNSigmaDe()); |
| 175 | + auto particle = particlesMC.iteratorAt(track.mcParticleId()); |
| 176 | + if (isPrimaryHe3(particle)) { |
| 177 | + if (std::abs(track.rapidity(MassHelium3)) < kMaxGenRapidity) { |
| 178 | + histo.fill(HIST("RecPt"), getSignedPtMC(particle)); |
| 179 | + } |
163 | 180 | } |
164 | 181 | } |
165 | 182 | } |
166 | 183 | } |
167 | 184 |
|
| 185 | + PROCESS_SWITCH(AntiNucleiTask, processMC, "processMC", true); |
168 | 186 | PROCESS_SWITCH(AntiNucleiTask, process, "process", true); |
169 | 187 | }; |
170 | 188 |
|
171 | 189 | WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) |
172 | 190 | { |
173 | | - return WorkflowSpec{ |
174 | | - adaptAnalysisTask<AntiNucleiTask>(cfgc)}; |
| 191 | + return WorkflowSpec{adaptAnalysisTask<AntiNucleiTask>(cfgc)}; |
175 | 192 | } |
0 commit comments