3434#include " Framework/RunningWorkflowInfo.h"
3535#include " Framework/StepTHn.h"
3636#include " Framework/runDataProcessing.h"
37+ #include " ReconstructionDataFormats/PID.h"
3738#include " ReconstructionDataFormats/Track.h"
3839#include < CCDB/BasicCCDBManager.h>
3940
@@ -63,8 +64,42 @@ using namespace o2;
6364using namespace o2 ::framework;
6465using namespace o2 ::framework::expressions;
6566
67+ static constexpr float LongArrayFloat[3 ][20 ] = {{1.1 , 1.2 , 1.3 , -1.1 , -1.2 , -1.3 , 1.1 , 1.2 , 1.3 , -1.1 , -1.2 , -1.3 , 1.1 , 1.2 , 1.3 , -1.1 , -1.2 , -1.3 , 1.1 , 1.2 }, {2.1 , 2.2 , 2.3 , -2.1 , -2.2 , -2.3 , 1.1 , 1.2 , 1.3 , -1.1 , -1.2 , -1.3 , 1.1 , 1.2 , 1.3 , -1.1 , -1.2 , -1.3 , 1.1 , 1.2 }, {3.1 , 3.2 , 3.3 , -3.1 , -3.2 , -3.3 , 1.1 , 1.2 , 1.3 , -1.1 , -1.2 , -1.3 , 1.1 , 1.2 , 1.3 , -1.1 , -1.2 , -1.3 , 1.1 , 1.2 }};
68+
6669struct V0ptHadPiKaProt {
6770
71+ // ITS response
72+ o2::aod::ITSResponse itsResponse;
73+ // Connect to ccdb
74+ Service<ccdb::BasicCCDBManager> ccdb;
75+ Configurable<int64_t > ccdbNoLaterThan{" ccdbNoLaterThan" , std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now ().time_since_epoch ()).count (), " latest acceptable timestamp of creation for the object" };
76+ Configurable<std::string> ccdbUrl{" ccdbUrl" , " http://ccdb-test.cern.ch:8080" , " url of the ccdb repository" };
77+
78+ enum Particles {
79+ PIONS = 0 ,
80+ KAONS,
81+ PROTONS
82+ };
83+ enum ParticleNsigma {
84+ kPionUpCut = 0 ,
85+ kKaonUpCut ,
86+ kProtonUpCut ,
87+ kPionLowCut ,
88+ kKaonLowCut ,
89+ kProtonLowCut
90+ };
91+ enum DetectorType {
92+ kTPC = 0 ,
93+ kTOF ,
94+ kITS
95+ };
96+ enum CentralityEstimator {
97+ kFT0C = 0 ,
98+ kFT0A ,
99+ kFT0M ,
100+ kFV0A
101+ };
102+
68103 Configurable<float > cfgCutVertex{" cfgCutVertex" , 10 .0f , " Accepted z-vertex range" };
69104 Configurable<float > cfgCutTpcChi2NCl{" cfgCutTpcChi2NCl" , 2 .5f , " Maximum TPCchi2NCl" };
70105 Configurable<float > cfgCutItsChi2NCl{" cfgCutItsChi2NCl" , 36 .0f , " Maximum ITSchi2NCl" };
@@ -87,16 +122,16 @@ struct V0ptHadPiKaProt {
87122 Configurable<float > cfgCutEtaLeft{" cfgCutEtaLeft" , 0 .8f , " Left end of eta gap" };
88123 Configurable<float > cfgCutEtaRight{" cfgCutEtaRight" , 0 .8f , " Right end of eta gap" };
89124 Configurable<int > cfgNSubsample{" cfgNSubsample" , 10 , " Number of subsamples" };
90- Configurable<int > cfgCentralityChoice{" cfgCentralityChoice" , 1 , " Which centrality estimator? 1 -->FT0C, 2 -->FT0A, 3 -->FT0M, 4 -->FV0A" };
125+ Configurable<int > cfgCentralityChoice{" cfgCentralityChoice" , 0 , " Which centrality estimator? 0 -->FT0C, 1 -->FT0A, 2 -->FT0M, 3 -->FV0A" };
91126 Configurable<bool > cfgEvSelkNoSameBunchPileup{" cfgEvSelkNoSameBunchPileup" , true , " Pileup removal" };
92127 Configurable<bool > cfgUseGoodITSLayerAllCut{" cfgUseGoodITSLayerAllCut" , true , " Remove time interval with dead ITS zone" };
93128 Configurable<bool > cfgEvSelkNoITSROFrameBorder{" cfgEvSelkNoITSROFrameBorder" , true , " ITSROFrame border event selection cut" };
94129 Configurable<bool > cfgEvSelkNoTimeFrameBorder{" cfgEvSelkNoTimeFrameBorder" , true , " TimeFrame border event selection cut" };
95-
96- // Connect to ccdb
97- Service<ccdb::BasicCCDBManager> ccdb ;
98- Configurable<int64_t > ccdbNoLaterThan{ " ccdbNoLaterThan " , std::chrono::duration_cast<std::chrono::milliseconds>( std::chrono::system_clock::now (). time_since_epoch ()). count (), " latest acceptable timestamp of creation for the object " };
99- Configurable<std::string> ccdbUrl{ " ccdbUrl " , " http://ccdb-test.cern.ch:8080 " , " url of the ccdb repository " };
130+ Configurable< bool > cfgEvSelUseGoodZvtxFT0vsPV{ " cfgEvSelUseGoodZvtxFT0vsPV " , true , " GoodZvertex and FT0 vs PV cut " };
131+ Configurable< bool > cfgUseItsPID{ " cfgUseItsPID " , false , " Use ITS PID for particle identification " };
132+ Configurable< float > cfgPtCutTOF{ " cfgPtCutTOF " , 0 . 3f , " Minimum pt to use TOF N-sigma " } ;
133+ Configurable<LabeledArray< float >> nSigmas{ " nSigmas " , {LongArrayFloat[ 0 ], 3 , 6 , { " TPC " , " TOF " , " ITS " }, { " pos_pi " , " pos_ka " , " pos_pr " , " neg_pi " , " neg_ka " , " neg_pr " }}, " Labeled array for n-sigma values for TPC, TOF, ITS for pions, kaons, protons (positive and negative) " };
134+ Configurable<bool > cfgUseRun3V2PID{ " cfgUseRun3V2PID " , true , " True if PID cuts to be used are similar to Run3 v2 PID analysis " };
100135
101136 HistogramRegistry histos{" Histos" , {}, OutputObjHandlingPolicy::AnalysisObject};
102137 std::vector<std::vector<std::shared_ptr<TProfile2D>>> subSample;
@@ -110,9 +145,35 @@ struct V0ptHadPiKaProt {
110145 using AodCollisions = soa::Filtered<soa::Join<aod::Collisions, aod::EvSels, aod::CentFV0As, aod::CentFT0Ms, aod::CentFT0As, aod::CentFT0Cs, aod::CentFDDMs, aod::Mults>>;
111146 using AodTracks = soa::Filtered<soa::Join<aod::Tracks, aod::TrackSelection, aod::TracksExtra, aod::TracksDCA, aod::pidTPCFullPr, aod::pidTOFFullPr, aod::pidTPCFullKa, aod::pidTOFFullKa, aod::pidTPCFullPi, aod::pidTOFFullPi, aod::pidTPCFullEl, aod::pidTOFFullEl>>;
112147
148+ std::array<float , 6 > tofNsigmaCut;
149+ std::array<float , 6 > itsNsigmaCut;
150+ std::array<float , 6 > tpcNsigmaCut;
151+
113152 // Equivalent of the AliRoot task UserCreateOutputObjects
114153 void init (o2::framework::InitContext&)
115154 {
155+ // Get nSigma values of TPC, TOF, ITS for various particles from the matrix "nSigmas"
156+ tpcNsigmaCut[kPionUpCut ] = nSigmas->getData ()[kTPC ][kPionUpCut ];
157+ tpcNsigmaCut[kKaonUpCut ] = nSigmas->getData ()[kTPC ][kKaonUpCut ];
158+ tpcNsigmaCut[kProtonUpCut ] = nSigmas->getData ()[kTPC ][kProtonUpCut ];
159+ tpcNsigmaCut[kPionLowCut ] = nSigmas->getData ()[kTPC ][kPionLowCut ];
160+ tpcNsigmaCut[kKaonLowCut ] = nSigmas->getData ()[kTPC ][kKaonLowCut ];
161+ tpcNsigmaCut[kProtonLowCut ] = nSigmas->getData ()[kTPC ][kProtonLowCut ];
162+
163+ tofNsigmaCut[kPionUpCut ] = nSigmas->getData ()[kTOF ][kPionUpCut ];
164+ tofNsigmaCut[kKaonUpCut ] = nSigmas->getData ()[kTOF ][kKaonUpCut ];
165+ tofNsigmaCut[kProtonUpCut ] = nSigmas->getData ()[kTOF ][kProtonUpCut ];
166+ tofNsigmaCut[kPionLowCut ] = nSigmas->getData ()[kTOF ][kPionLowCut ];
167+ tofNsigmaCut[kKaonLowCut ] = nSigmas->getData ()[kTOF ][kKaonLowCut ];
168+ tofNsigmaCut[kProtonLowCut ] = nSigmas->getData ()[kTOF ][kProtonLowCut ];
169+
170+ itsNsigmaCut[kPionUpCut ] = nSigmas->getData ()[kITS ][kPionUpCut ];
171+ itsNsigmaCut[kKaonUpCut ] = nSigmas->getData ()[kITS ][kKaonUpCut ];
172+ itsNsigmaCut[kProtonUpCut ] = nSigmas->getData ()[kITS ][kProtonUpCut ];
173+ itsNsigmaCut[kPionLowCut ] = nSigmas->getData ()[kITS ][kPionLowCut ];
174+ itsNsigmaCut[kKaonLowCut ] = nSigmas->getData ()[kITS ][kKaonLowCut ];
175+ itsNsigmaCut[kProtonLowCut ] = nSigmas->getData ()[kITS ][kProtonLowCut ];
176+
116177 // Define axes
117178 std::vector<double > ptBin = {0.2 , 0.4 , 0.6 , 0.8 , 1.0 , 1.2 , 1.4 , 1.6 , 1.8 , 2.0 , 2.2 , 2.4 , 2.6 , 2.8 , 3.0 , 3.5 , 4.0 , 5.0 , 6.0 , 8.0 , 10.0 };
118179 AxisSpec ptAxis = {ptBin, " #it{p}_{T} (GeV/#it{c})" };
@@ -332,6 +393,56 @@ struct V0ptHadPiKaProt {
332393 return false ;
333394 }
334395
396+ template <typename TTrack>
397+ int getNsigmaPID (TTrack track)
398+ {
399+ // Computing Nsigma arrays for pion, kaon, and protons
400+ std::array<float , 3 > nSigmaTPC = {track.tpcNSigmaPi (), track.tpcNSigmaKa (), track.tpcNSigmaPr ()};
401+ std::array<float , 3 > nSigmaTOF = {track.tofNSigmaPi (), track.tofNSigmaKa (), track.tofNSigmaPr ()};
402+ std::array<float , 3 > nSigmaITS = {itsResponse.nSigmaITS <o2::track::PID::Pion>(track), itsResponse.nSigmaITS <o2::track::PID::Kaon>(track), itsResponse.nSigmaITS <o2::track::PID::Proton>(track)};
403+ int pid = 0 ; // 0 = not identified, 1 = pion, 2 = kaon, 3 = proton
404+
405+ std::array<float , 3 > nSigmaToUse = cfgUseItsPID ? nSigmaITS : nSigmaTPC; // Choose which nSigma to use: TPC or ITS
406+ std::array<float , 6 > detectorNsigmaCut = cfgUseItsPID ? itsNsigmaCut : tpcNsigmaCut; // Choose which nSigma to use: TPC or ITS
407+
408+ bool isPion, isKaon, isProton;
409+ bool isDetectedPion = nSigmaToUse[PIONS] < detectorNsigmaCut[kPionUpCut ] && nSigmaToUse[PIONS] > detectorNsigmaCut[kPionLowCut ];
410+ bool isDetectedKaon = nSigmaToUse[KAONS] < detectorNsigmaCut[kKaonUpCut ] && nSigmaToUse[KAONS] > detectorNsigmaCut[kKaonLowCut ];
411+ bool isDetectedProton = nSigmaToUse[PROTONS] < detectorNsigmaCut[kProtonUpCut ] && nSigmaToUse[PROTONS] > detectorNsigmaCut[kProtonLowCut ];
412+
413+ bool isTofPion = nSigmaTOF[PIONS] < tofNsigmaCut[kPionUpCut ] && nSigmaTOF[PIONS] > tofNsigmaCut[kPionLowCut ];
414+ bool isTofKaon = nSigmaTOF[KAONS] < tofNsigmaCut[kKaonUpCut ] && nSigmaTOF[KAONS] > tofNsigmaCut[kKaonLowCut ];
415+ bool isTofProton = nSigmaTOF[PROTONS] < tofNsigmaCut[kProtonUpCut ] && nSigmaTOF[PROTONS] > tofNsigmaCut[kProtonLowCut ];
416+
417+ if (track.pt () > cfgPtCutTOF && !track.hasTOF ()) {
418+ return 0 ;
419+ } else if (track.pt () > cfgPtCutTOF && track.hasTOF ()) {
420+ isPion = isTofPion && isDetectedPion;
421+ isKaon = isTofKaon && isDetectedKaon;
422+ isProton = isTofProton && isDetectedProton;
423+ } else {
424+ isPion = isDetectedPion;
425+ isKaon = isDetectedKaon;
426+ isProton = isDetectedProton;
427+ }
428+
429+ if ((isPion && isKaon) || (isPion && isProton) || (isKaon && isProton)) {
430+ return 0 ; // more than one particle satisfy the criteria
431+ }
432+
433+ if (isPion) {
434+ pid = PIONS + 1 ;
435+ } else if (isKaon) {
436+ pid = KAONS + 1 ;
437+ } else if (isProton) {
438+ pid = PROTONS + 1 ;
439+ } else {
440+ return 0 ; // no particle satisfies the criteria
441+ }
442+
443+ return pid; // 0 = not identified, 1 = pion, 2 = kaon, 3 = proton
444+ }
445+
335446 // process Data
336447 void process (AodCollisions::iterator const & coll, aod::BCsWithTimestamps const &, AodTracks const & inputTracks)
337448 {
@@ -350,16 +461,19 @@ struct V0ptHadPiKaProt {
350461 if (cfgEvSelkNoTimeFrameBorder && !(coll.selection_bit (o2::aod::evsel::kNoTimeFrameBorder ))) {
351462 return ;
352463 }
464+ if (cfgEvSelUseGoodZvtxFT0vsPV && !(coll.selection_bit (o2::aod::evsel::kIsGoodZvtxFT0vsPV ))) {
465+ return ;
466+ }
353467
354468 // Centrality
355469 double cent = 0.0 ;
356- if (cfgCentralityChoice == 1 )
470+ if (cfgCentralityChoice == kFT0C )
357471 cent = coll.centFT0C ();
358- else if (cfgCentralityChoice == 2 )
472+ else if (cfgCentralityChoice == kFT0A )
359473 cent = coll.centFT0A ();
360- else if (cfgCentralityChoice == 3 )
474+ else if (cfgCentralityChoice == kFT0M )
361475 cent = coll.centFT0M ();
362- else if (cfgCentralityChoice == 4 )
476+ else if (cfgCentralityChoice == kFV0A )
363477 cent = coll.centFV0A ();
364478
365479 histos.fill (HIST (" hZvtx_after_sel" ), coll.posZ ());
@@ -438,9 +552,23 @@ struct V0ptHadPiKaProt {
438552 histos.fill (HIST (" h2DnsigmaProtonTpcVsTofBeforeCut" ), nSigmaTpcProt, nSigmaTofProt);
439553
440554 // identified particles selection
441- bool isPion = selectionPion (track);
442- bool isKaon = selectionKaon (track);
443- bool isProton = selectionProton (track);
555+ bool isPion = false ;
556+ bool isKaon = false ;
557+ bool isProton = false ;
558+
559+ if (cfgUseRun3V2PID) {
560+ int pidVal = getNsigmaPID (track);
561+ if (pidVal == PIONS + 1 )
562+ isPion = true ;
563+ if (pidVal == KAONS + 1 )
564+ isKaon = true ;
565+ if (pidVal == PROTONS + 1 )
566+ isProton = true ;
567+ } else {
568+ isPion = selectionPion (track);
569+ isKaon = selectionKaon (track);
570+ isProton = selectionProton (track);
571+ }
444572
445573 // PID QAs after selection
446574 if (isPion) {
0 commit comments