1313// / \file uecharged.cxx
1414// / \brief Underlying event analysis task
1515// / \since November 2021
16- // / \last update: January 2026
16+ // / \last update: March 2026
1717
1818#include " PWGLF/DataModel/mcCentrality.h"
1919#include " PWGLF/Utils/collisionCuts.h"
@@ -50,47 +50,6 @@ using FT0s = aod::FT0s;
5050
5151struct ueCharged {
5252
53- TrackSelection myTrackSelectionPrim ()
54- {
55- TrackSelection selectedTracks;
56- selectedTracks.SetPtRange (0 .1f , 1e10f);
57- selectedTracks.SetEtaRange (-0 .8f , 0 .8f );
58- selectedTracks.SetRequireITSRefit (true );
59- selectedTracks.SetRequireTPCRefit (true );
60- selectedTracks.SetRequireGoldenChi2 (true );
61- selectedTracks.SetMinNCrossedRowsTPC (70 );
62- selectedTracks.SetMinNCrossedRowsOverFindableClustersTPC (0 .8f );
63- selectedTracks.SetMaxChi2PerClusterTPC (4 .f );
64- selectedTracks.SetRequireHitsInITSLayers (1 , {0 , 1 , 2 }); // Run3ITSibAny
65- selectedTracks.SetMaxChi2PerClusterITS (36 .f );
66- selectedTracks.SetMaxDcaXYPtDep ([](float pt) { return 0 .0105f + 0 .0350f / std::pow (pt, 1 .1f ); });
67- selectedTracks.SetMaxDcaZ (0 .1f );
68- return selectedTracks;
69- }
70-
71- TrackSelection myTrackSelectionOpenDCA ()
72- {
73- TrackSelection selectedTracks;
74- selectedTracks.SetPtRange (0 .1f , 1e10f);
75- selectedTracks.SetEtaRange (-0 .8f , 0 .8f );
76- selectedTracks.SetRequireITSRefit (true );
77- selectedTracks.SetRequireTPCRefit (true );
78- selectedTracks.SetRequireGoldenChi2 (true );
79- selectedTracks.SetMinNCrossedRowsTPC (70 );
80- selectedTracks.SetMinNCrossedRowsOverFindableClustersTPC (0 .8f );
81- selectedTracks.SetMaxChi2PerClusterTPC (4 .f );
82- selectedTracks.SetRequireHitsInITSLayers (1 , {0 , 1 , 2 }); // Run3ITSibAny
83- selectedTracks.SetMaxChi2PerClusterITS (36 .f );
84- selectedTracks.SetMaxDcaXYPtDep ([](float pt) { return 0 .0105f + 0 .0350f / pow (pt, 1 .1f ); });
85- selectedTracks.SetMaxDcaZ (0 .1f );
86- return selectedTracks;
87- }
88-
89- TrackSelection mySelectionPrim;
90- TrackSelection mySelectionOpenDCA;
91-
92- Service<o2::framework::O2DatabasePDG> pdg;
93-
9453 // Configurable for event selection
9554 Configurable<bool > isRun3{" isRun3" , true , " is Run3 dataset" };
9655 Configurable<bool > pileuprejection{" pileuprejection" , true , " Pileup rejection" };
@@ -99,9 +58,27 @@ struct ueCharged {
9958 Configurable<bool > removeITSROFBorder{" removeITSROFBorder" , false , " Remove ITS Read-Out Frame border and only apply kIsTriggerTVX & kNoTimeFrameBorder (recommended for MC)" };
10059 Configurable<int > cfgINELCut{" cfgINELCut" , 0 , " INEL event selection: 0 no sel, 1 INEL>0, 2 INEL>1" };
10160 Configurable<bool > analyzeEvandTracksel{" analyzeEvandTracksel" , true , " Analyze the event and track selection" };
102- // acceptance cuts
103- Configurable<float > cfgTrkEtaCut{" cfgTrkEtaCut" , 0 .8f , " Eta range for tracks" };
61+
62+ // Track selection configurables
63+ TrackSelection myTrkSel;
10464 Configurable<float > cfgTrkLowPtCut{" cfgTrkLowPtCut" , 0 .15f , " Minimum constituent pT" };
65+ Configurable<bool > isCustomTracks{" isCustomTracks" , true , " Use custom track cuts" };
66+ Configurable<int > setITSreq{" setITSreq" , 0 , " 0 = Run3ITSibAny, 1 = Run3ITSallAny, 2 = Run3ITSall7Layers, 3 = Run3ITSibTwo" };
67+ Configurable<float > minPt{" minPt" , 0 .1f , " Set minimum pT of tracks" };
68+ Configurable<float > maxPt{" maxPt" , 1e10f, " Set maximum pT of tracks" };
69+ Configurable<float > requireEta{" requireEta" , 0 .8f , " Set eta range of tracks" };
70+ Configurable<bool > requireITSRefit{" requireITSRefit" , true , " Additional cut on the ITS requirement" };
71+ Configurable<bool > requireTPCRefit{" requireTPCRefit" , true , " Additional cut on the TPC requirement" };
72+ Configurable<bool > requireGoldenChi2{" requireGoldenChi2" , true , " Additional cut on the GoldenChi2" };
73+ Configurable<float > maxChi2PerClusterTPC{" maxChi2PerClusterTPC" , 4 .f , " Additional cut on the maximum value of the chi2 per cluster in the TPC" };
74+ Configurable<float > maxChi2PerClusterITS{" maxChi2PerClusterITS" , 36 .f , " Additional cut on the maximum value of the chi2 per cluster in the ITS" };
75+ // Configurable<int> minITSnClusters{"minITSnClusters", 5, "minimum number of found ITS clusters"};
76+ Configurable<float > minNCrossedRowsTPC{" minNCrossedRowsTPC" , 70 .f , " Additional cut on the minimum number of crossed rows in the TPC" };
77+ Configurable<float > minNCrossedRowsOverFindableClustersTPC{" minNCrossedRowsOverFindableClustersTPC" , 0 .8f , " Additional cut on the minimum value of the ratio between crossed rows and findable clusters in the TPC" };
78+ Configurable<float > maxDcaXYFactor{" maxDcaXYFactor" , 1 .f , " Multiplicative factor on the maximum value of the DCA xy" };
79+ Configurable<float > maxDcaZ{" maxDcaZ" , 0 .1f , " Additional cut on the maximum value of the DCA z" };
80+
81+ Service<o2::framework::O2DatabasePDG> pdg;
10582
10683 // Data table definitions
10784 using ColDataTable = soa::Join<aod::Collisions, aod::EvSels, aod::Mults, aod::PVMults>;
@@ -152,6 +129,24 @@ struct ueCharged {
152129 void init (InitContext const &)
153130 {
154131
132+ if (isCustomTracks.value ) {
133+ myTrkSel = getGlobalTrackSelectionRun3ITSMatch (setITSreq.value );
134+ myTrkSel.SetPtRange (minPt.value , maxPt.value );
135+ myTrkSel.SetEtaRange (-requireEta.value , requireEta.value );
136+ myTrkSel.SetRequireITSRefit (requireITSRefit.value );
137+ myTrkSel.SetRequireTPCRefit (requireTPCRefit.value );
138+ myTrkSel.SetRequireGoldenChi2 (requireGoldenChi2.value );
139+ myTrkSel.SetMaxChi2PerClusterTPC (maxChi2PerClusterTPC.value );
140+ myTrkSel.SetMaxChi2PerClusterITS (maxChi2PerClusterITS.value );
141+ // myTrkSel.SetMinNClustersITS(minITSnClusters.value);
142+ myTrkSel.SetMinNCrossedRowsTPC (minNCrossedRowsTPC.value );
143+ myTrkSel.SetMinNCrossedRowsOverFindableClustersTPC (minNCrossedRowsOverFindableClustersTPC.value );
144+ // myTrkSel.SetMaxDcaXYPtDep([](float pt) { return 0.0105f + 0.0350f / pow(pt, 1.1f); });
145+ myTrkSel.SetMaxDcaXYPtDep ([](float /* pt*/ ) { return 10000 .f ; });
146+ myTrkSel.SetMaxDcaZ (maxDcaZ.value );
147+ myTrkSel.print ();
148+ }
149+
155150 ConfigurableAxis ptBinningt{" ptBinningt" ,
156151 {0 , 0.15 , 0.50 , 1.00 , 1.50 , 2.00 , 2.50 ,
157152 3.00 , 3.50 , 4.00 , 4.50 , 5.00 , 6.00 , 7.00 ,
@@ -325,16 +320,41 @@ struct ueCharged {
325320 if (!track.has_collision ()) {
326321 return false ;
327322 }
328- if (!mySelectionPrim. IsSelected (track) ) {
323+ if (track. pt () < cfgTrkLowPtCut ) {
329324 return false ;
330325 }
331- if (std::abs (track.eta ()) >= cfgTrkEtaCut) {
332- return false ;
326+ if (isCustomTracks.value ) {
327+ for (int i = 0 ; i < static_cast <int >(TrackSelection::TrackCuts::kNCuts ); i++) {
328+ if (i == static_cast <int >(TrackSelection::TrackCuts::kDCAxy )) {
329+ continue ;
330+ }
331+ if (!myTrkSel.IsSelected (track, static_cast <TrackSelection::TrackCuts>(i))) {
332+ return false ;
333+ }
334+ }
335+ return (std::abs (track.dcaXY ()) <= (maxDcaXYFactor.value * (0 .0105f + 0 .0350f / std::pow (track.pt (), 1 .1f ))));
333336 }
334- if (track.pt () < cfgTrkLowPtCut) {
335- return false ;
337+ return track.isGlobalTrack ();
338+ }
339+
340+ template <typename T>
341+ bool isDCAxyWoCut (T const & track) // function to skip DCA track selections
342+ {
343+ if (isCustomTracks.value ) {
344+ for (int i = 0 ; i < static_cast <int >(TrackSelection::TrackCuts::kNCuts ); i++) {
345+ if (i == static_cast <int >(TrackSelection::TrackCuts::kDCAxy )) {
346+ continue ;
347+ }
348+ if (i == static_cast <int >(TrackSelection::TrackCuts::kDCAz )) {
349+ continue ;
350+ }
351+ if (!myTrkSel.IsSelected (track, static_cast <TrackSelection::TrackCuts>(i))) {
352+ return false ;
353+ }
354+ }
355+ return true ;
336356 }
337- return true ;
357+ return track. isGlobalTrackWoDCA () ;
338358 }
339359
340360 template <typename P>
@@ -350,7 +370,7 @@ struct ueCharged {
350370 if (!pdgParticle || pdgParticle->Charge () == 0 .) {
351371 return false ;
352372 }
353- if (std::abs (particle.eta ()) >= cfgTrkEtaCut ) {
373+ if (std::abs (particle.eta ()) >= requireEta ) {
354374 return false ;
355375 }
356376 if (particle.pt () < cfgTrkLowPtCut) {
@@ -508,7 +528,7 @@ struct ueCharged {
508528 std::vector<int > indexArray;
509529
510530 for (const auto & track : tracks) {
511- if (mySelectionOpenDCA. IsSelected (track))
531+ if (isDCAxyWoCut (track))
512532 ue.fill (HIST (" hPTVsDCAData" ), track.pt (), track.dcaXY ());
513533
514534 if (isTrackSelected (track)) {
@@ -667,6 +687,10 @@ struct ueCharged {
667687 if (!foundRec)
668688 return ;
669689
690+ if (analyzeEvandTracksel) {
691+ analyzeEventAndTrackSelection (chosenRec, RecTracks.sliceBy (perCollision, chosenRecGlobalIndex));
692+ }
693+
670694 // compute truth-level leading particle and truth-region observables
671695 double flPtTrue = 0 .;
672696 double flPhiTrue = 0 .;
@@ -762,7 +786,7 @@ struct ueCharged {
762786 if (!pdgParticle || pdgParticle->Charge () == 0 .) {
763787 continue ;
764788 }
765- if (std::abs (particle.eta ()) >= cfgTrkEtaCut ) {
789+ if (std::abs (particle.eta ()) >= requireEta ) {
766790 continue ;
767791 }
768792
@@ -832,7 +856,7 @@ struct ueCharged {
832856 if (track.collisionId () != chosenRecGlobalIndex)
833857 continue ;
834858
835- if (mySelectionOpenDCA. IsSelected (track))
859+ if (isDCAxyWoCut (track))
836860 ue.fill (HIST (" hPTVsDCAData" ), track.pt (), track.dcaXY ());
837861
838862 if (track.has_mcParticle ()) {
@@ -843,20 +867,20 @@ struct ueCharged {
843867
844868 if (isTrackSelected (track))
845869 ue.fill (HIST (" hPtOut" ), track.pt ());
846- if (mySelectionOpenDCA. IsSelected (track))
870+ if (isDCAxyWoCut (track))
847871 ue.fill (HIST (" hPtDCAall" ), track.pt (), track.dcaXY ());
848872
849873 if (particle.isPhysicalPrimary () && particle.producedByGenerator ()) { // primary particles
850874 if (isTrackSelected (track) && isParticleSelected (particle)) { // TODO check if this condition
851875 ue.fill (HIST (" hPtOutPrim" ), particle.pt ());
852876 }
853- if (mySelectionOpenDCA. IsSelected (track)) {
877+ if (isDCAxyWoCut (track)) {
854878 ue.fill (HIST (" hPtDCAPrimary" ), track.pt (), track.dcaXY ());
855879 }
856880 } else { // Secondaries (weak decays and material)
857881 if (isTrackSelected (track))
858882 ue.fill (HIST (" hPtOutSec" ), track.pt ());
859- if (mySelectionOpenDCA. IsSelected (track)) {
883+ if (isDCAxyWoCut (track)) {
860884 if (particle.getProcess () == 4 )
861885 ue.fill (HIST (" hPtDCAWeak" ), track.pt (), track.dcaXY ());
862886 else
@@ -996,7 +1020,7 @@ struct ueCharged {
9961020 auto pdgParticle = pdg->GetParticle (particle.pdgCode ());
9971021 if (!pdgParticle || pdgParticle->Charge () == 0 .)
9981022 continue ;
999- if (std::abs (particle.eta ()) >= cfgTrkEtaCut )
1023+ if (std::abs (particle.eta ()) >= requireEta )
10001024 continue ;
10011025 multTrue++;
10021026 if (particle.pt () < cfgTrkLowPtCut)
@@ -1145,7 +1169,7 @@ struct ueCharged {
11451169 tracks_before++;
11461170 }
11471171
1148- if (mySelectionPrim. IsSelected (track)) {
1172+ if (isTrackSelected (track)) {
11491173 if (track.hasITS () && track.hasTPC ()) {
11501174 ue.fill (HIST (" postselection_track/ITS/itsNCls" ), track.itsNCls ());
11511175 ue.fill (HIST (" postselection_track/ITS/itsChi2NCl" ), track.itsChi2NCl ());
0 commit comments