@@ -83,20 +83,31 @@ struct HResonanceCorrelationFilter {
8383 Configurable<bool > cfgEvtSel8{" cfgEvtSel8" , true , " Evt Sel 8 check for offline selection" };
8484 Configurable<bool > cfgEvtNoSameBunchPileupCut{" cfgEvtNoSameBunchPileupCut" , true , " Evt sel: reject collisions associated with the same found-by-T0 bunch crossing" };
8585 Configurable<bool > cfgEvtGoodZvtxFT0vsPVCut{" cfgEvtGoodZvtxFT0vsPVCut" , true , " Evt sel: require small difference between z-vertex from PV and from FT0" };
86+ // Centrality source switch for hCentralitySelected: O-O collisions have a
87+ // well-defined FT0C centrality estimator; p-O (asymmetric system) does
88+ // not, so FV0A is used there instead. Only affects which estimator is
89+ // read for that one QA histogram -- doesn't change any selection cut.
90+ Configurable<bool > cfgUseFV0ACentrality{" cfgUseFV0ACentrality" , false , " Centrality estimator for hCentralitySelected: false = O-O (FT0C), true = p-O (FV0A)" };
8691 } configEvents;
8792
8893 // Merged from the formerly separate configTracks/generalSelections/
8994 // trackSelections groups -- all three were "cuts applied to a track or
9095 // track pair", just split by who last touched them. No member names
9196 // collided, so every Configurable below keeps its original key; only the
9297 // "<group>." prefix at each call site changed, to configTracks.
98+ // General, species-agnostic track-quality cuts: applied identically to
99+ // every track that reaches trackCut() -- trigger, associated hadron, AND
100+ // Phi/K*0 daughter candidates alike (see trackCut() below, and its call
101+ // sites at isValidTrigger(), isValidAssocTrack<Species>(), and both
102+ // processPhis()/processKstars()). cfgCutEta/cMinPtcut additionally gate
103+ // the framework-level `acceptanceFilter` Filter, applied to every track
104+ // in every process function before any of the above ever sees it.
93105 struct : ConfigurableGroup {
94106 std::string prefix = " configTracks" ;
95107 // Pre-selection Track cuts
96108 Configurable<float > cMinPtcut{" cMinPtcut" , 0 .15f , " Minimal pT for tracks" };
97109 Configurable<float > cMinTPCNClsFound{" cMinTPCNClsFound" , 120 , " minimum TPCNClsFound value for good track" };
98110 Configurable<float > cfgCutEta{" cfgCutEta" , 0 .8f , " Eta range for tracks" };
99- Configurable<float > cfgCutRapidity{" cfgCutRapidity" , 0 .5f , " rapidity range for particles" };
100111 Configurable<int > cfgMinCrossedRows{" cfgMinCrossedRows" , 70 , " min crossed rows for good track" };
101112 Configurable<float > cfgMaxTPCChi2NCl{" cfgMaxTPCChi2NCl" , 4 .0f , " max TPC chi2/clusters for good track" };
102113 Configurable<float > cfgMaxITSChi2NCl{" cfgMaxITSChi2NCl" , 36 .0f , " max ITS chi2/clusters for good track" };
@@ -115,30 +126,49 @@ struct HResonanceCorrelationFilter {
115126 Configurable<bool > cfgHasTOF{" cfgHasTOF" , false , " Require TOF" };
116127 Configurable<bool > cTPCNClsFound{" cTPCNClsFound" , false , " Switch to turn on/off TPCNClsFound cut" };
117128
118- // Associated particle selections in phase space (formerly generalSelections)
119- Configurable<float > assocEtaMin{" assocEtaMin" , -0.8 , " triggeretamin" };
120- Configurable<float > assocEtaMax{" assocEtaMax" , 0.8 , " triggeretamax" };
121- Configurable<float > assocPtCutMin{" assocPtCutMin" , 0.2 , " assocptmin" };
122- Configurable<float > assocPtCutMax{" assocPtCutMax" , 10 , " assocptmax" };
129+ // Track quality shared by trigger AND assoc selection (isValidTrigger()
130+ // and isValidAssocTrack<Species>() both read this same configurable --
131+ // it is NOT split into trigger-/assoc-only copies below).
132+ Configurable<int > minTPCNCrossedRows{" minTPCNCrossedRows" , 70 , " Minimum TPC crossed rows" };
123133
124- // Trigger particle selections in phase space (formerly generalSelections)
134+ // primary particle DCAxy selections (formerly trackSelections)
135+ // formula: |DCAxy| < 0.004f + (0.013f / pt)
136+ Configurable<float > dcaXYconstant{" dcaXYconstant" , 0.004 , " [0] in |DCAxy| < [0]+[1]/pT" };
137+ Configurable<float > dcaXYpTdep{" dcaXYpTdep" , 0.013 , " [1] in |DCAxy| < [0]+[1]/pT" };
138+ } configTracks;
139+
140+ // Phi/K*0 resonance-candidate cuts: applied to the RECONSTRUCTED candidate
141+ // (the K+K- or K-pi 4-vector), not to the daughter tracks themselves --
142+ // the daughters go through the shared configTracks/trackCut() cuts above
143+ // like every other track. Currently holds just the one configurable; kept
144+ // as its own group rather than folded into configTracks so it reads as
145+ // "resonance-level", not "track-level".
146+ struct : ConfigurableGroup {
147+ std::string prefix = " configResoDauTracks" ;
148+ Configurable<float > cfgCutRapidity{" cfgCutRapidity" , 0 .5f , " rapidity range for the reconstructed Phi/K*0 candidate" };
149+ } configResoDauTracks;
150+
151+ // Trigger-hadron-only phase-space and quality cuts.
152+ struct : ConfigurableGroup {
153+ std::string prefix = " configTriggerTracks" ;
125154 Configurable<float > triggerEtaMin{" triggerEtaMin" , -0.8 , " triggeretamin" };
126155 Configurable<float > triggerEtaMax{" triggerEtaMax" , 0.8 , " triggeretamax" };
127- Configurable<float > triggerPtCutMin{" triggerPtCutMin" , 3 , " triggerptmin" };
156+ Configurable<float > triggerPtCutMin{" triggerPtCutMin" , 2 , " triggerptmin" };
128157 Configurable<float > triggerPtCutMax{" triggerPtCutMax" , 20 , " triggerptmax" };
129-
130- // Track quality (formerly trackSelections)
131- Configurable<int > minTPCNCrossedRows{" minTPCNCrossedRows" , 70 , " Minimum TPC crossed rows" };
132158 Configurable<bool > triggerRequireITS{" triggerRequireITS" , true , " require ITS signal in trigger tracks" };
133- Configurable<bool > assocRequireITS{" assocRequireITS" , true , " require ITS signal in assoc tracks" };
134159 Configurable<int > triggerMaxTPCSharedClusters{" triggerMaxTPCSharedClusters" , 200 , " maximum number of shared TPC clusters (inclusive)" };
135160 Configurable<bool > triggerRequireL0{" triggerRequireL0" , false , " require ITS L0 cluster for trigger" };
161+ } configTriggerTracks;
136162
137- // primary particle DCAxy selections (formerly trackSelections)
138- // formula: |DCAxy| < 0.004f + (0.013f / pt)
139- Configurable<float > dcaXYconstant{" dcaXYconstant" , 0.004 , " [0] in |DCAxy| < [0]+[1]/pT" };
140- Configurable<float > dcaXYpTdep{" dcaXYpTdep" , 0.013 , " [1] in |DCAxy| < [0]+[1]/pT" };
141- } configTracks;
163+ // Associated-hadron-only phase-space and quality cuts.
164+ struct : ConfigurableGroup {
165+ std::string prefix = " configAssocTracks" ;
166+ Configurable<float > assocEtaMin{" assocEtaMin" , -0.8 , " triggeretamin" };
167+ Configurable<float > assocEtaMax{" assocEtaMax" , 0.8 , " triggeretamax" };
168+ Configurable<float > assocPtCutMin{" assocPtCutMin" , 0.2 , " assocptmin" };
169+ Configurable<float > assocPtCutMax{" assocPtCutMax" , 10 , " assocptmax" };
170+ Configurable<bool > assocRequireITS{" assocRequireITS" , true , " require ITS signal in assoc tracks" };
171+ } configAssocTracks;
142172
143173 struct : ConfigurableGroup {
144174 std::string prefix = " configPID" ;
@@ -181,15 +211,6 @@ struct HResonanceCorrelationFilter {
181211 Configurable<float > rejectSigma{" rejectSigma" , 1 , " n sigma for rejecting pion candidates" };
182212 } configPID;
183213
184- // Unused in this file today -- nothing here reads from CCDB any more
185- // (Zorro was the only consumer and has been removed). Kept (grouped,
186- // rather than removed) since that's outside today's ask.
187- struct : ConfigurableGroup {
188- std::string prefix = " ccdbConfigurations" ;
189- Configurable<std::string> ccdburl{" ccdburl" , " http://alice-ccdb.cern.ch" , " url of the ccdb repository to use" };
190- Configurable<std::string> parameterCCDBPath{" parameterCCDBPath" , " Users/k/kcui/LHC25b4a/parameter" , " Path of the mean and sigma" };
191- } ccdbConfigurations;
192-
193214 // must include windows for background and peak
194215 //
195216 // This filter-level cut is an acceptance pre-cut only -- it decides what
@@ -238,6 +259,8 @@ struct HResonanceCorrelationFilter {
238259 ConfigurableAxis axisDCAxyQA{" axisDCAxyQA" , {200 , -0 .5f , 0 .5f }, " DCA_{xy} (cm)" };
239260 ConfigurableAxis axisDCAzQA{" axisDCAzQA" , {200 , -0 .5f , 0 .5f }, " DCA_{z} (cm)" };
240261 ConfigurableAxis axisTPCCrossedRowsQA{" axisTPCCrossedRowsQA" , {160 , 0 , 160 }, " TPC crossed rows" };
262+ ConfigurableAxis axisVertexZQA{" axisVertexZQA" , {60 , -15 .0f , 15 .0f }, " Vertex Z (cm)" };
263+ ConfigurableAxis axisCentralityQA{" axisCentralityQA" , {100 , 0 .0f , 100 .0f }, " Centrality (%)" };
241264 } axesConfigurations;
242265
243266 // QA
@@ -292,6 +315,12 @@ struct HResonanceCorrelationFilter {
292315 void init (InitContext const &)
293316 {
294317 histos.add (" CollCutCounts" , " No. of event after cuts" , kTH1I , {{10 , 0 , 10 }});
318+ // Z-vertex and centrality of selected events (filled in isSelectedEvents()
319+ // once a collision passes every cut, i.e. the same "All Passed Events"
320+ // point as CollCutCounts bin 8). Centrality source for the latter is
321+ // configEvents.cfgUseFV0ACentrality: FT0C for O-O, FV0A for p-O.
322+ histos.add (" hVertexZSelected" , " Vertex Z of selected events" , kTH1F , {axesConfigurations.axisVertexZQA });
323+ histos.add (" hCentralitySelected" , " Centrality of selected events" , kTH1F , {axesConfigurations.axisCentralityQA });
295324 histos.get <TH1 >(HIST (" CollCutCounts" ))->GetXaxis ()->SetBinLabel (1 , " All Events" );
296325 histos.get <TH1 >(HIST (" CollCutCounts" ))->GetXaxis ()->SetBinLabel (2 , " |Vz| < cut" );
297326 histos.get <TH1 >(HIST (" CollCutCounts" ))->GetXaxis ()->SetBinLabel (3 , " kIsTriggerTVX" );
@@ -326,6 +355,8 @@ struct HResonanceCorrelationFilter {
326355 histos.add ((dir + " /hPtVsDCAz" ).c_str (), " p_{T} vs DCA_{z}" , kTH2F , {axesConfigurations.axisPtQA , axesConfigurations.axisDCAzQA });
327356 histos.add ((dir + " /hPtVsTPCNSigma" ).c_str (), " p_{T} vs TPC n#sigma" , kTH2F , {axesConfigurations.axisPtQA , axesConfigurations.axisNSigmaQA });
328357 histos.add ((dir + " /hPtVsTOFNSigma" ).c_str (), " p_{T} vs TOF n#sigma" , kTH2F , {axesConfigurations.axisPtQA , axesConfigurations.axisNSigmaQA });
358+ // TPC vs TOF nSigma correlation, for the usual PID "banana plot" check
359+ histos.add ((dir + " /hTPCNSigmaVsTOFNSigma" ).c_str (), " TPC n#sigma vs TOF n#sigma" , kTH2F , {axesConfigurations.axisNSigmaQA , axesConfigurations.axisNSigmaQA });
329360 };
330361 bookDaughterQA (" QA/Phi/Kaon" );
331362 bookDaughterQA (" QA/Kstar/Kaon" );
@@ -360,6 +391,9 @@ struct HResonanceCorrelationFilter {
360391 histos.fill (HIST (" QA/Phi/Kaon/hPtVsDCAz" ), track.pt (), track.dcaZ ());
361392 histos.fill (HIST (" QA/Phi/Kaon/hPtVsTPCNSigma" ), track.pt (), track.tpcNSigmaKa ());
362393 histos.fill (HIST (" QA/Phi/Kaon/hPtVsTOFNSigma" ), track.pt (), track.tofNSigmaKa ());
394+ if (track.hasTOF ()) {
395+ histos.fill (HIST (" QA/Phi/Kaon/hTPCNSigmaVsTOFNSigma" ), track.tpcNSigmaKa (), track.tofNSigmaKa ());
396+ }
363397 }
364398
365399 template <typename Track>
@@ -376,6 +410,9 @@ struct HResonanceCorrelationFilter {
376410 histos.fill (HIST (" QA/Kstar/Kaon/hPtVsDCAz" ), track.pt (), track.dcaZ ());
377411 histos.fill (HIST (" QA/Kstar/Kaon/hPtVsTPCNSigma" ), track.pt (), track.tpcNSigmaKa ());
378412 histos.fill (HIST (" QA/Kstar/Kaon/hPtVsTOFNSigma" ), track.pt (), track.tofNSigmaKa ());
413+ if (track.hasTOF ()) {
414+ histos.fill (HIST (" QA/Kstar/Kaon/hTPCNSigmaVsTOFNSigma" ), track.tpcNSigmaKa (), track.tofNSigmaKa ());
415+ }
379416 }
380417
381418 template <typename Track>
@@ -392,6 +429,9 @@ struct HResonanceCorrelationFilter {
392429 histos.fill (HIST (" QA/Kstar/Pion/hPtVsDCAz" ), track.pt (), track.dcaZ ());
393430 histos.fill (HIST (" QA/Kstar/Pion/hPtVsTPCNSigma" ), track.pt (), track.tpcNSigmaPi ());
394431 histos.fill (HIST (" QA/Kstar/Pion/hPtVsTOFNSigma" ), track.pt (), track.tofNSigmaPi ());
432+ if (track.hasTOF ()) {
433+ histos.fill (HIST (" QA/Kstar/Pion/hTPCNSigmaVsTOFNSigma" ), track.tpcNSigmaPi (), track.tofNSigmaPi ());
434+ }
395435 }
396436
397437 // Trigger hadrons carry no PID selection, so only the 5 non-PID variables
@@ -463,6 +503,14 @@ struct HResonanceCorrelationFilter {
463503
464504 if (fillHist) {
465505 histos.fill (HIST (" CollCutCounts" ), 8 );
506+ histos.fill (HIST (" hVertexZSelected" ), collision.posZ ());
507+ // Guarded with if constexpr: isSelectedEvents() is called with several
508+ // different collision join types (some callers pass fillHist=false and
509+ // don't join centrality tables at all), so this only compiles/fills for
510+ // callers whose collision type actually has both estimators joined.
511+ if constexpr (requires { collision.centFT0C (); collision.centFV0A (); }) {
512+ histos.fill (HIST (" hCentralitySelected" ), configEvents.cfgUseFV0ACentrality ? collision.centFV0A () : collision.centFT0C ());
513+ }
466514 }
467515
468516 return true ;
@@ -692,23 +740,23 @@ struct HResonanceCorrelationFilter {
692740 if (!trackCut (track)) {
693741 return false ;
694742 }
695- if (track.eta () > configTracks .triggerEtaMax || track.eta () < configTracks .triggerEtaMin ) {
743+ if (track.eta () > configTriggerTracks .triggerEtaMax || track.eta () < configTriggerTracks .triggerEtaMin ) {
696744 return false ;
697745 }
698746 // if (track.sign()= 1 ) {continue;}
699- if (track.pt () > configTracks .triggerPtCutMax || track.pt () < configTracks .triggerPtCutMin ) {
747+ if (track.pt () > configTriggerTracks .triggerPtCutMax || track.pt () < configTriggerTracks .triggerPtCutMin ) {
700748 return false ;
701749 }
702750 if (track.tpcNClsCrossedRows () < configTracks.minTPCNCrossedRows ) {
703751 return false ; // crossed rows
704752 }
705- if (!track.hasITS () && configTracks .triggerRequireITS ) {
753+ if (!track.hasITS () && configTriggerTracks .triggerRequireITS ) {
706754 return false ; // skip, doesn't have ITS signal (skips lots of TPC-only!)
707755 }
708- if (track.tpcNClsShared () > configTracks .triggerMaxTPCSharedClusters ) {
756+ if (track.tpcNClsShared () > configTriggerTracks .triggerMaxTPCSharedClusters ) {
709757 return false ; // skip, has shared clusters
710758 }
711- if (!(BIT_CHECK (track.itsClusterMap (), 0 )) && configTracks .triggerRequireL0 ) {
759+ if (!(BIT_CHECK (track.itsClusterMap (), 0 )) && configTriggerTracks .triggerRequireL0 ) {
712760 return false ; // skip, doesn't have cluster in ITS L0
713761 }
714762 return true ;
@@ -743,16 +791,16 @@ struct HResonanceCorrelationFilter {
743791 if (!trackCut (assoc)) {
744792 return false ;
745793 }
746- if (assoc.eta () > configTracks .assocEtaMax || assoc.eta () < configTracks .assocEtaMin ) {
794+ if (assoc.eta () > configAssocTracks .assocEtaMax || assoc.eta () < configAssocTracks .assocEtaMin ) {
747795 return false ;
748796 }
749- if (assoc.pt () > configTracks .assocPtCutMax || assoc.pt () < configTracks .assocPtCutMin ) {
797+ if (assoc.pt () > configAssocTracks .assocPtCutMax || assoc.pt () < configAssocTracks .assocPtCutMin ) {
750798 return false ;
751799 }
752800 if (assoc.tpcNClsCrossedRows () < configTracks.minTPCNCrossedRows ) {
753801 return false ; // crossed rows
754802 }
755- if (!assoc.hasITS () && configTracks .assocRequireITS ) {
803+ if (!assoc.hasITS () && configAssocTracks .assocRequireITS ) {
756804 return false ; // skip, doesn't have ITS signal (skips lots of TPC-only!)
757805 }
758806
@@ -855,7 +903,7 @@ struct HResonanceCorrelationFilter {
855903 }
856904
857905 // for real data processing
858- void processTriggers (soa::Join<aod::Collisions, aod::EvSels, aod::CentFT0Ms, aod::CentFT0Cs, aod::PVMults>::iterator const & collision, soa::Filtered<FullTracks> const & tracks)
906+ void processTriggers (soa::Join<aod::Collisions, aod::EvSels, aod::CentFT0Ms, aod::CentFT0Cs, aod::CentFV0As, aod:: PVMults>::iterator const & collision, soa::Filtered<FullTracks> const & tracks)
859907 {
860908 triggerCandidates.clear ();
861909 if (!isSelectedEvents (collision)) {
@@ -894,7 +942,7 @@ struct HResonanceCorrelationFilter {
894942 }
895943
896944 // for MC processing
897- void processTriggersMC (soa::Join<aod::Collisions, aod::EvSels, aod::CentFT0Ms, aod::CentFT0Cs, aod::PVMults>::iterator const & collision, soa::Filtered<FullTracksMC> const & tracks, aod::McParticles const &)
945+ void processTriggersMC (soa::Join<aod::Collisions, aod::EvSels, aod::CentFT0Ms, aod::CentFT0Cs, aod::CentFV0As, aod:: PVMults>::iterator const & collision, soa::Filtered<FullTracksMC> const & tracks, aod::McParticles const &)
898946 {
899947 triggerCandidates.clear ();
900948 if (!isSelectedEvents (collision)) {
@@ -1090,7 +1138,7 @@ struct HResonanceCorrelationFilter {
10901138 float invMass = phi.M ();
10911139
10921140 // rapidity cut
1093- if (std::abs (phi.Rapidity ()) > configTracks .cfgCutRapidity ) {
1141+ if (std::abs (phi.Rapidity ()) > configResoDauTracks .cfgCutRapidity ) {
10941142 continue ;
10951143 }
10961144
@@ -1181,7 +1229,7 @@ struct HResonanceCorrelationFilter {
11811229 float invMass = phi.M ();
11821230
11831231 // rapidity cut
1184- if (std::abs (phi.Rapidity ()) > configTracks .cfgCutRapidity ) {
1232+ if (std::abs (phi.Rapidity ()) > configResoDauTracks .cfgCutRapidity ) {
11851233 continue ;
11861234 }
11871235
@@ -1299,7 +1347,7 @@ struct HResonanceCorrelationFilter {
12991347 float invMass = kstar.M ();
13001348
13011349 // rapidity cut
1302- if (std::abs (kstar.Rapidity ()) > configTracks .cfgCutRapidity ) {
1350+ if (std::abs (kstar.Rapidity ()) > configResoDauTracks .cfgCutRapidity ) {
13031351 continue ;
13041352 }
13051353
@@ -1388,7 +1436,7 @@ struct HResonanceCorrelationFilter {
13881436 float invMass = kstar.M ();
13891437
13901438 // rapidity cut
1391- if (std::abs (kstar.Rapidity ()) > configTracks .cfgCutRapidity ) {
1439+ if (std::abs (kstar.Rapidity ()) > configResoDauTracks .cfgCutRapidity ) {
13921440 continue ;
13931441 }
13941442
0 commit comments