Skip to content

Commit 942862a

Browse files
authored
Add new task to study multiplicity distributions
1 parent ba2d931 commit 942862a

File tree

1 file changed

+339
-0
lines changed

1 file changed

+339
-0
lines changed
Lines changed: 339 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,339 @@
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 studyPnch.cxx
13+
///
14+
/// \brief task for analysis of charged-particle multiplicity distributions
15+
/// \author Abhi Modak (abhi.modak@cern.ch)
16+
/// \since September 10, 2025
17+
18+
#include <cmath>
19+
#include <cstdlib>
20+
#include <TPDGCode.h>
21+
#include <vector>
22+
23+
#include "PWGMM/Mult/DataModel/bestCollisionTable.h"
24+
#include "CCDB/BasicCCDBManager.h"
25+
#include "Common/Core/trackUtilities.h"
26+
#include "Common/CCDB/EventSelectionParams.h"
27+
#include "Common/Core/TrackSelection.h"
28+
#include "Common/DataModel/Centrality.h"
29+
#include "Common/DataModel/Multiplicity.h"
30+
#include "Common/DataModel/EventSelection.h"
31+
#include "Common/DataModel/TrackSelectionTables.h"
32+
#include "CommonConstants/MathConstants.h"
33+
#include "Framework/ASoAHelpers.h"
34+
#include "Framework/AnalysisDataModel.h"
35+
#include "Framework/AnalysisTask.h"
36+
#include "Framework/Configurable.h"
37+
#include "Framework/O2DatabasePDGPlugin.h"
38+
#include "Framework/runDataProcessing.h"
39+
#include "ReconstructionDataFormats/GlobalTrackID.h"
40+
#include "ReconstructionDataFormats/Track.h"
41+
#include "PWGMM/Mult/DataModel/Index.h"
42+
#include "Common/DataModel/PIDResponse.h"
43+
#include "PWGLF/DataModel/LFStrangenessTables.h"
44+
45+
using namespace o2;
46+
using namespace o2::framework;
47+
using namespace o2::framework::expressions;
48+
using namespace o2::aod::track;
49+
using namespace o2::aod::evsel;
50+
51+
using ColDataTable = soa::Join<aod::Collisions, aod::EvSels, aod::Mults, aod::PVMults>;
52+
using TrackDataTable = soa::Join<aod::Tracks, aod::TracksExtra, aod::TracksDCA, aod::TrackSelection>;
53+
using FilTrackDataTable = soa::Filtered<TrackDataTable>;
54+
using ColMCTrueTable = aod::McCollisions;
55+
using TrackMCTrueTable = aod::McParticles;
56+
using ColMCRecTable = soa::SmallGroups<soa::Join<aod::McCollisionLabels, aod::Collisions, aod::EvSels, aod::Mults, aod::PVMults>>;
57+
using TrackMCRecTable = soa::Join<aod::Tracks, aod::TracksExtra, aod::TracksDCA, aod::McTrackLabels, aod::TrackSelection>;
58+
using FilTrackMCRecTable = soa::Filtered<TrackMCRecTable>;
59+
60+
static constexpr TrackSelectionFlags::flagtype TrackSelectionIts =
61+
TrackSelectionFlags::kITSNCls | TrackSelectionFlags::kITSChi2NDF |
62+
TrackSelectionFlags::kITSHits;
63+
static constexpr TrackSelectionFlags::flagtype TrackSelectionTpc =
64+
TrackSelectionFlags::kTPCNCls |
65+
TrackSelectionFlags::kTPCCrossedRowsOverNCls |
66+
TrackSelectionFlags::kTPCChi2NDF;
67+
static constexpr TrackSelectionFlags::flagtype TrackSelectionDca =
68+
TrackSelectionFlags::kDCAz | TrackSelectionFlags::kDCAxy;
69+
static constexpr TrackSelectionFlags::flagtype TrackSelectionDcaxyOnly =
70+
TrackSelectionFlags::kDCAxy;
71+
72+
AxisSpec axisEvent{10, 0.5, 10.5, "#Event", "EventAxis"};
73+
AxisSpec axisVtxZ{40, -20, 20, "Vertex Z", "VzAxis"};
74+
AxisSpec axisEta{40, -2, 2, "#eta", "EtaAxis"};
75+
AxisSpec axisPhi{629, 0, o2::constants::math::TwoPI, "#phi"};
76+
auto static constexpr kMinCharge = 3.f;
77+
auto static constexpr kMinpTcut = 0.1f;
78+
79+
struct StudyPnch {
80+
81+
HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject};
82+
Service<o2::framework::O2DatabasePDG> pdg;
83+
Preslice<TrackMCRecTable> perCollision = aod::track::collisionId;
84+
85+
Configurable<float> etaRange{"etaRange", 1.0f, "Eta range to consider"};
86+
Configurable<float> vtxRange{"vtxRange", 10.0f, "Vertex Z range to consider"};
87+
Configurable<float> dcaZ{"dcaZ", 0.2f, "Custom DCA Z cut (ignored if negative)"};
88+
Configurable<float> extraphicut1{"extraphicut1", 3.07666f, "Extra Phi cut 1"};
89+
Configurable<float> extraphicut2{"extraphicut2", 3.12661f, "Extra Phi cut 2"};
90+
Configurable<float> extraphicut3{"extraphicut3", 0.03f, "Extra Phi cut 3"};
91+
Configurable<float> extraphicut4{"extraphicut4", 6.253f, "Extra Phi cut 4"};
92+
ConfigurableAxis multHistBin{"multHistBin", {501, -0.5, 500.5}, ""};
93+
ConfigurableAxis pvHistBin{"pvHistBin", {501, -0.5, 500.5}, ""};
94+
ConfigurableAxis fv0aMultHistBin{"fv0aMultHistBin", {501, -0.5, 500.5}, ""};
95+
ConfigurableAxis ft0aMultHistBin{"ft0aMultHistBin", {501, -0.5, 500.5}, ""};
96+
ConfigurableAxis ft0cMultHistBin{"ft0cMultHistBin", {501, -0.5, 500.5}, ""};
97+
ConfigurableAxis ptHistBin{"ptHistBin", {200, 0., 20.}, ""};
98+
99+
Configurable<bool> isApplyTFcut{"isApplyTFcut", true, "Enable TimeFrameBorder cut"};
100+
Configurable<bool> isApplyITSROcut{"isApplyITSROcut", true, "Enable ITS ReadOutFrameBorder cut"};
101+
Configurable<bool> isApplySameBunchPileup{"isApplySameBunchPileup", true, "Enable SameBunchPileup cut"};
102+
Configurable<bool> isApplyInelgt0{"isApplyInelgt0", false, "Enable INEL > 0 condition"};
103+
Configurable<bool> isApplyExtraPhiCut{"isApplyExtraPhiCut", false, "Enable extra phi cut"};
104+
105+
void init(InitContext const&)
106+
{
107+
AxisSpec axisMult = {multHistBin, "Mult", "MultAxis"};
108+
AxisSpec axisPV = {pvHistBin, "PV", "PVAxis"};
109+
AxisSpec axisFv0aMult = {fv0aMultHistBin, "fv0a", "FV0AMultAxis"};
110+
AxisSpec axisFt0aMult = {ft0aMultHistBin, "ft0a", "FT0AMultAxis"};
111+
AxisSpec axisFt0cMult = {ft0cMultHistBin, "ft0c", "FT0CMultAxis"};
112+
AxisSpec axisPt = {ptHistBin, "pT", "pTAxis"};
113+
114+
histos.add("EventHist", "EventHist", kTH1D, {axisEvent}, false);
115+
histos.add("VtxZHist", "VtxZHist", kTH1D, {axisVtxZ}, false);
116+
117+
auto hstat = histos.get<TH1>(HIST("EventHist"));
118+
auto* x = hstat->GetXaxis();
119+
x->SetBinLabel(1, "All events");
120+
x->SetBinLabel(2, "kIsTriggerTVX");
121+
x->SetBinLabel(3, "kNoTimeFrameBorder");
122+
x->SetBinLabel(4, "kNoITSROFrameBorder");
123+
x->SetBinLabel(5, "kNoSameBunchPileup"); // reject collisions in case of pileup with another collision in the same foundBC
124+
x->SetBinLabel(6, "INEL > 0");
125+
x->SetBinLabel(7, "|vz| < 10");
126+
127+
if (doprocessData || doprocessCorrelation || doprocessMonteCarlo) {
128+
histos.add("PhiVsEtaHist", "PhiVsEtaHist", kTH2F, {axisPhi, axisEta}, false);
129+
}
130+
if (doprocessData) {
131+
histos.add("hMultiplicityData", "hMultiplicityData", kTH1F, {axisMult}, true);
132+
}
133+
if (doprocessCorrelation) {
134+
histos.add("GlobalMult_vs_FT0A", "GlobalMult_vs_FT0A", kTH2F, {axisMult, axisFt0aMult}, true);
135+
histos.add("GlobalMult_vs_FT0C", "GlobalMult_vs_FT0C", kTH2F, {axisMult, axisFt0cMult}, true);
136+
histos.add("GlobalMult_vs_FV0A", "GlobalMult_vs_FV0A", kTH2F, {axisMult, axisFv0aMult}, true);
137+
histos.add("NPVtracks_vs_FT0C", "NPVtracks_vs_FT0C", kTH2F, {axisPV, axisFt0cMult}, true);
138+
histos.add("NPVtracks_vs_GlobalMult", "NPVtracks_vs_GlobalMult", kTH2F, {axisPV, axisMult}, true);
139+
}
140+
if (doprocessMonteCarlo) {
141+
histos.add("hMultiplicityMCrec", "hMultiplicityMCrec", kTH1F, {axisMult}, true);
142+
histos.add("hMultiplicityMCgen", "hMultiplicityMCgen", kTH1F, {axisMult}, true);
143+
histos.add("hResponseMatrix", "hResponseMatrix", kTH2F, {axisMult, axisMult}, true);
144+
}
145+
if (doprocessEvtLossSigLossMC) {
146+
histos.add("MCEventHist", "MCEventHist", kTH1F, {axisEvent}, false);
147+
auto hstat = histos.get<TH1>(HIST("MCEventHist"));
148+
auto* x = hstat->GetXaxis();
149+
x->SetBinLabel(1, "All MC events");
150+
x->SetBinLabel(2, "MC events with atleast one reco event");
151+
histos.add("hMultiplicityMCgenAll", "hMultiplicityMCgenAll", kTH1F, {axisMult}, true);
152+
histos.add("hMultiplicityMCgenSel", "hMultiplicityMCgenSel", kTH1F, {axisMult}, true);
153+
}
154+
}
155+
156+
template <typename CheckCol>
157+
bool isEventSelected(CheckCol const& col)
158+
{
159+
histos.fill(HIST("EventHist"), 1);
160+
if (!col.selection_bit(o2::aod::evsel::kIsTriggerTVX)) {
161+
return false;
162+
}
163+
histos.fill(HIST("EventHist"), 2);
164+
if (isApplyTFcut && !col.selection_bit(o2::aod::evsel::kNoTimeFrameBorder)) {
165+
return false;
166+
}
167+
histos.fill(HIST("EventHist"), 3);
168+
if (isApplyITSROcut && !col.selection_bit(o2::aod::evsel::kNoITSROFrameBorder)) {
169+
return false;
170+
}
171+
histos.fill(HIST("EventHist"), 4);
172+
if (isApplySameBunchPileup && !col.selection_bit(o2::aod::evsel::kNoSameBunchPileup)) {
173+
return false;
174+
}
175+
histos.fill(HIST("EventHist"), 5);
176+
if (isApplyInelgt0 && !col.isInelGt0()) {
177+
return false;
178+
}
179+
histos.fill(HIST("EventHist"), 6);
180+
if (std::abs(col.posZ()) >= vtxRange) {
181+
return;
182+
}
183+
histos.fill(HIST("EventHist"), 7);
184+
histos.fill(HIST("VtxZHist"), col.posZ());
185+
}
186+
187+
template <typename CheckTrack>
188+
bool isTrackSelected(CheckTrack const& track)
189+
{
190+
if (std::abs(track.eta()) >= etaRange) {
191+
return false;
192+
}
193+
if (isApplyExtraPhiCut && ((track.phi() > extraphicut1 && track.phi() < extraphicut2) || track.phi() <= extraphicut3 || track.phi() >= extraphicut4)) {
194+
return false;
195+
}
196+
return true;
197+
}
198+
199+
template <typename CheckGenTrack>
200+
bool isGenTrackSelected(CheckGenTrack const& track)
201+
{
202+
if (!track.isPhysicalPrimary()) {
203+
return false;
204+
}
205+
if (!track.producedByGenerator()) {
206+
return false;
207+
}
208+
auto pdgTrack = pdg->GetParticle(track.pdgCode());
209+
if (pdgTrack == nullptr) {
210+
return false;
211+
}
212+
if (std::abs(pdgTrack->Charge()) < kMinCharge) {
213+
return false;
214+
}
215+
if (std::abs(track.eta()) >= etaRange) {
216+
return false;
217+
}
218+
if (isApplyExtraPhiCut && ((track.phi() > extraphicut1 && track.phi() < extraphicut2) || track.phi() <= extraphicut3 || track.phi() >= extraphicut4)) {
219+
return false;
220+
}
221+
return true;
222+
}
223+
224+
template <typename countTrk>
225+
int countNTracks(countTrk const& tracks)
226+
{
227+
auto nTrk = 0;
228+
for (const auto& track : tracks) {
229+
if (!isTrackSelected(track)) {
230+
continue;
231+
}
232+
histos.fill(HIST("PhiVsEtaHist"), track.phi(), track.eta());
233+
nTrk++;
234+
}
235+
return nTrk;
236+
}
237+
238+
template <typename countTrk>
239+
int countGenTracks(countTrk const& tracks)
240+
{
241+
auto nTrk = 0;
242+
for (const auto& track : tracks) {
243+
if (!isGenTrackSelected(track)) {
244+
continue;
245+
}
246+
histos.fill(HIST("PhiVsEtaHist"), track.phi(), track.eta());
247+
nTrk++;
248+
}
249+
return nTrk;
250+
}
251+
252+
Filter fTrackSelectionITS = ncheckbit(aod::track::v001::detectorMap, (uint8_t)o2::aod::track::ITS) &&
253+
ncheckbit(aod::track::trackCutFlag, TrackSelectionIts);
254+
Filter fTrackSelectionTPC = ifnode(ncheckbit(aod::track::v001::detectorMap, (uint8_t)o2::aod::track::TPC),
255+
ncheckbit(aod::track::trackCutFlag, TrackSelectionTpc), true);
256+
Filter fTrackSelectionDCA = ifnode(dcaZ.node() > 0.f, nabs(aod::track::dcaZ) <= dcaZ && ncheckbit(aod::track::trackCutFlag, TrackSelectionDcaxyOnly),
257+
ncheckbit(aod::track::trackCutFlag, TrackSelectionDca));
258+
259+
void processData(ColDataTable::iterator const& cols, FilTrackDataTable const& tracks)
260+
{
261+
if (!isEventSelected(cols)) {
262+
return;
263+
}
264+
auto mult = countNTracks(tracks);
265+
histos.fill(HIST("hMultiplicityData"), mult);
266+
}
267+
268+
void processCorrelation(ColDataTable::iterator const& cols, FilTrackDataTable const& tracks)
269+
{
270+
if (!isEventSelected(cols)) {
271+
return;
272+
}
273+
auto mult = countNTracks(tracks);
274+
histos.fill(HIST("GlobalMult_vs_FT0A"), nchTracks, cols.multFT0A());
275+
histos.fill(HIST("GlobalMult_vs_FT0C"), nchTracks, cols.multFT0C());
276+
histos.fill(HIST("GlobalMult_vs_FV0A"), nchTracks, cols.multFV0A());
277+
histos.fill(HIST("NPVtracks_vs_FT0C"), cols.multNTracksPV(), cols.multFT0C());
278+
histos.fill(HIST("NPVtracks_vs_GlobalMult"), cols.multNTracksPV(), nchTracks);
279+
}
280+
281+
void processMonteCarlo(ColMCTrueTable::iterator const&, ColMCRecTable const& RecCols, TrackMCTrueTable const& GenParticles, FilTrackMCRecTable const& RecTracks)
282+
{
283+
for (const auto& RecCol : RecCols) {
284+
if (!isEventSelected(RecCol)) {
285+
continue;
286+
}
287+
auto recTracksPart = RecTracks.sliceBy(perCollision, RecCol.globalIndex());
288+
auto multrec = countNTracks(recTracksPart);
289+
histos.fill(HIST("hMultiplicityMCrec"), multrec);
290+
auto multgen = countGenTracks(GenParticles);
291+
histos.fill(HIST("hMultiplicityMCgen"), multgen);
292+
histos.fill(HIST("hResponseMatrix"), multrec, multgen);
293+
}
294+
}
295+
296+
void processEvtLossSigLossMC(soa::Join<ColMCTrueTable, aod::MultMCExtras>::iterator const& mcCollision, ColMCRecTable const& RecCols, TrackMCTrueTable const& GenParticles)
297+
{
298+
if (isApplyInelgt0 && !mcCollision.isInelGt0()) {
299+
return;
300+
}
301+
if (std::abs(mcCollision.posZ()) >= vtxRange) {
302+
return;
303+
}
304+
// All generated events
305+
histos.fill(HIST("MCEventHist"), 1);
306+
auto multAll = countGenTracks(GenParticles);
307+
histos.fill(HIST("hMultiplicityMCgenAll"), multAll);
308+
309+
bool atLeastOne = false;
310+
auto numcontributors = -999;
311+
for (const auto& RecCol : RecCols) {
312+
if (!isEventSelected(RecCol)) {
313+
continue;
314+
}
315+
if (RecCol.numContrib() <= numcontributors) {
316+
continue;
317+
} else {
318+
numcontributors = RecCol.numContrib();
319+
}
320+
atLeastOne = true;
321+
}
322+
323+
if (atLeastOne) {
324+
histos.fill(HIST("MCEventHist"), 2);
325+
auto multSel = countGenTracks(GenParticles);
326+
histos.fill(HIST("hMultiplicityMCgenSel"), multSel);
327+
}
328+
}
329+
330+
PROCESS_SWITCH(HeavyionMultiplicity, processData, "process data CentFT0C", false);
331+
PROCESS_SWITCH(HeavyionMultiplicity, processCorrelation, "do correlation study in data", false);
332+
PROCESS_SWITCH(HeavyionMultiplicity, processMonteCarlo, "process MC CentFT0C", false);
333+
PROCESS_SWITCH(HeavyionMultiplicity, processEvtLossSigLossMC, "process Signal Loss, Event Loss", false);
334+
};
335+
336+
WorkflowSpec defineDataProcessing(ConfigContext const& cfgc)
337+
{
338+
return WorkflowSpec{adaptAnalysisTask<StudyPnch>(cfgc)};
339+
}

0 commit comments

Comments
 (0)