1515
1616#include " Framework/runDataProcessing.h"
1717#include " Framework/AnalysisTask.h"
18+ #include " Common/DataModel/TrackSelectionTables.h"
19+ #include " Framework/ASoAHelpers.h"
20+
21+ #include < TPDGCode.h> // for PDG codes
1822
1923using namespace o2 ;
2024using namespace o2 ::framework;
25+ using namespace o2 ::framework::expressions;
2126
2227struct myExampleTask {
2328 // Histogram registry: an object to hold your histograms
2429 HistogramRegistry histos{" histos" , {}, OutputObjHandlingPolicy::AnalysisObject};
2530
31+ Configurable<int > nBinsPt{" nBinsPt" , 100 , " N bins in pT histo" };
32+ Configurable<float > maxDCAxy{" maxDCAxy" , 0.2 , " max DCAxy (in cm)" };
33+ Configurable<float > minTPCCrossedRows{" minTPCCrossedRows" , 70 , " min crossed rows in the TPC" };
34+
35+ Filter trackDCA = nabs(aod::track::dcaXY) < maxDCAxy;
36+
37+ // This is an example of a convenient declaration of "using"
38+ using myCompleteTracksMC = soa::Join<aod::Tracks, aod::TracksExtra, aod::TracksDCA, aod::McTrackLabels>;
39+ using myCompleteTracks = soa::Join<aod::Tracks, aod::TracksExtra, aod::TracksDCA>;
40+ using myFilteredTracksMC = soa::Filtered<myCompleteTracksMC>;
41+ using myFilteredTracks = soa::Filtered<myCompleteTracks>;
42+
43+ Preslice<aod::Tracks> perCollision = aod::track::collisionId;
44+
2645 void init (InitContext const &)
2746 {
2847 // define axes you want to use
48+ const AxisSpec axisCounter{1 , 0 , +1 , " " };
2949 const AxisSpec axisEta{30 , -1.5 , +1.5 , " #eta" };
30-
50+ const AxisSpec axisPt{nBinsPt, 0 , 10 , " p_{T}" };
51+ const AxisSpec axisDeltaPt{100 , -1.0 , +1.0 , " #Delta(p_{T})" };
3152 // create histograms
53+ histos.add (" eventCounter" , " eventCounter" , kTH1F , {axisCounter});
3254 histos.add (" etaHistogram" , " etaHistogram" , kTH1F , {axisEta});
55+ histos.add (" ptHistogram" , " ptHistogram" , kTH1F , {axisPt});
56+ histos.add (" ptResolution" , " ptResolution" , kTH2F , {axisPt, axisDeltaPt});
57+
58+ histos.add (" ptHistogramPion" , " ptHistogramPion" , kTH1F , {axisPt});
59+ histos.add (" ptHistogramKaon" , " ptHistogramKaon" , kTH1F , {axisPt});
60+ histos.add (" ptHistogramProton" , " ptHistogramProton" , kTH1F , {axisPt});
61+ histos.add (" ptGeneratedPion" , " ptGeneratedPion" , kTH1F , {axisPt});
62+ histos.add (" ptGeneratedKaon" , " ptGeneratedKaon" , kTH1F , {axisPt});
63+ histos.add (" ptGeneratedProton" , " ptGeneratedProton" , kTH1F , {axisPt});
64+
65+ histos.add (" numberOfRecoCollisions" , " numberOfRecoCollisions" , kTH1F , {{10 ,-0 .5f , 9 .5f }});
66+ histos.add (" multiplicityCorrelation" , " multiplicityCorrelations" , kTH2F , {{100 , -0 .5f , 99 .5f }, {100 ,-0 .5f , 99 .5f }});
3367 }
3468
35- void process (aod::TracksIU const & tracks)
36- {
37- for (auto & track : tracks) {
69+ template <bool fillResolution = true , typename TCollision, typename TTracks>
70+ void processStuff (TCollision const & collision, TTracks const & tracks) {
71+ histos.fill (HIST (" eventCounter" ), 0 .5f );
72+ for (const auto & track : tracks) {
73+ if ( track.tpcNClsCrossedRows () < minTPCCrossedRows ) continue ; // badly tracked
3874 histos.fill (HIST (" etaHistogram" ), track.eta ());
75+ histos.fill (HIST (" ptHistogram" ), track.pt ());
76+
77+ // this part only done if dealing with MC
78+ if constexpr (requires { track.has_mcParticle (); }) { // does the getter exist?
79+ if (track.has_mcParticle ()){ // is the return 'true'? -> N.B. different question!
80+ auto mcParticle = track.mcParticle ();
81+ if constexpr (fillResolution){ // compile-time check
82+ histos.fill (HIST (" ptResolution" ), track.pt (), track.pt () - mcParticle.pt ());
83+ }
84+ if (mcParticle.isPhysicalPrimary () && fabs (mcParticle.y ())<0.5 ){ // do this in the context of the track ! (context matters!!!)
85+ if (abs (mcParticle.pdgCode ())==kPiPlus ) histos.fill (HIST (" ptHistogramPion" ), mcParticle.pt ());
86+ if (abs (mcParticle.pdgCode ())==kKPlus ) histos.fill (HIST (" ptHistogramKaon" ), mcParticle.pt ());
87+ if (abs (mcParticle.pdgCode ())==kProton ) histos.fill (HIST (" ptHistogramProton" ), mcParticle.pt ());
88+ }
89+ }
90+ }
91+ }
92+ }
93+
94+ void processRecoInData (aod::Collision const & collision, myFilteredTracks const & tracks)
95+ {
96+ processStuff (collision, tracks);
97+ }
98+ PROCESS_SWITCH (myExampleTask, processRecoInData, " process reconstructed information" , true );
99+
100+ void processRecoInSim (aod::Collision const & collision, myFilteredTracksMC const & tracks, aod::McParticles const &)
101+ {
102+ processStuff (collision, tracks);
103+ }
104+ PROCESS_SWITCH (myExampleTask, processRecoInSim, " process reconstructed information" , false );
105+
106+ void processSim (aod::McCollision const & mcCollision, soa::SmallGroups<soa::Join<aod::McCollisionLabels, aod::Collisions>> const & collisions, aod::McParticles const & mcParticles, myFilteredTracksMC const & tracks)
107+ {
108+ histos.fill (HIST (" numberOfRecoCollisions" ), collisions.size ()); // number of times coll was reco-ed
109+
110+ // Now loop over each time this collision has been reconstructed and aggregate tracks
111+ std::vector<int > numberOfTracks;
112+ for (auto & collision : collisions) {
113+ auto groupedTracks = tracks.sliceBy (perCollision, collision.globalIndex ());
114+ // size of grouped tracks may help in understanding why event was split!
115+ numberOfTracks.emplace_back (groupedTracks.size ());
116+ }
117+ if ( collisions.size () == 2 ) histos.fill (HIST (" multiplicityCorrelation" ), numberOfTracks[0 ], numberOfTracks[1 ]);
118+
119+ // Loop over particles in this mcCollision (first argument of process: iterator)
120+ for (const auto & mcParticle : mcParticles) {
121+ if (mcParticle.isPhysicalPrimary () && fabs (mcParticle.y ())<0.5 ){ // do this in the context of the MC loop ! (context matters!!!)
122+ if (abs (mcParticle.pdgCode ())==kPiPlus ) histos.fill (HIST (" ptGeneratedPion" ), mcParticle.pt ());
123+ if (abs (mcParticle.pdgCode ())==kKPlus ) histos.fill (HIST (" ptGeneratedKaon" ), mcParticle.pt ());
124+ if (abs (mcParticle.pdgCode ())==kProton ) histos.fill (HIST (" ptGeneratedProton" ), mcParticle.pt ());
125+ }
39126 }
40127 }
128+ PROCESS_SWITCH (myExampleTask, processSim, " process pure simulation information" , false );
41129};
42130
43131WorkflowSpec defineDataProcessing (ConfigContext const & cfgc)
44132{
45133 return WorkflowSpec{
46134 adaptAnalysisTask<myExampleTask>(cfgc)};
47- }
135+ }
0 commit comments