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 LFResonanceInitializer.cxx
13+ // / \brief Initializes variables for the resonance candidate producers
14+ // /
15+ // /
16+ // / \author Bong-Hwi Lim <bong-hwi.lim@cern.ch>
17+
18+ #include " Common/DataModel/PIDResponse.h"
19+ #include " Common/Core/TrackSelection.h"
20+ #include " Common/DataModel/Centrality.h"
21+ #include " Common/DataModel/Multiplicity.h"
22+ #include " Common/Core/trackUtilities.h"
23+ #include " Common/DataModel/EventSelection.h"
24+ #include " Common/DataModel/StrangenessTables.h"
25+ #include " Common/DataModel/TrackSelectionTables.h"
26+ #include " Framework/ASoAHelpers.h"
27+ #include " Framework/AnalysisDataModel.h"
28+ #include " Framework/AnalysisTask.h"
29+ #include " Framework/runDataProcessing.h"
30+ #include " PWGLF/DataModel/LFResonanceTables.h"
31+ #include " PWGLF/Utils/collisionCuts.h"
32+ #include " ReconstructionDataFormats/Track.h"
33+
34+ using namespace o2 ;
35+ using namespace o2 ::framework;
36+ using namespace o2 ::framework::expressions;
37+ using namespace o2 ::soa;
38+
39+ // / Initializer for the resonance candidate producers
40+ struct reso2initializer {
41+
42+ Produces<aod::ResoCollisions> resoCollisions;
43+ Produces<aod::ResoDaughters> reso2tracks;
44+
45+ // Configurables
46+ Configurable<bool > ConfIsRun3{" ConfIsRun3" , false , " Running on Pilot beam" }; // Choose if running on converted data or pilot beam
47+ Configurable<bool > ConfStoreV0{" ConfStoreV0" , true , " True: store V0s" };
48+
49+ // / Event cuts
50+ o2::analysis::CollisonCuts colCuts;
51+ Configurable<float > ConfEvtZvtx{" ConfEvtZvtx" , 10 .f , " Evt sel: Max. z-Vertex (cm)" };
52+ Configurable<bool > ConfEvtTriggerCheck{" ConfEvtTriggerCheck" , true , " Evt sel: check for trigger" };
53+ Configurable<int > ConfEvtTriggerSel{" ConfEvtTriggerSel" , kINT7 , " Evt sel: trigger" };
54+ Configurable<bool > ConfEvtOfflineCheck{" ConfEvtOfflineCheck" , false , " Evt sel: check for offline selection" };
55+
56+ // Pre-selection cuts
57+ Configurable<float > cfgCutEta{" cfgCutEta" , 0 .8f , " Eta range for tracks" };
58+ Configurable<float > pidnSigmaPreSelectionCut{" pidnSigmaPreSelectionCut" , 5 .0f , " TPC and TOF PID cut (loose, improve performance)" };
59+ Configurable<int > mincrossedrows{" mincrossedrows" , 70 , " min crossed rows" };
60+ Configurable<int > isRun2{" isRun2" , 0 , " if Run2: demand TPC refit" };
61+
62+ // / DCA Selections for V0
63+ // DCAr to PV
64+ Configurable<double > cMaxDCArToPVcut{" cMaxDCArToPVcut" , 0.05 , " Track DCAr cut to PV Maximum" };
65+ Configurable<double > cMinV0PosDCArToPVcut{" cMinV0PosDCArToPVcut" , 0 .05f , " V0 Positive Track DCAr cut to PV Minimum" }; // Pre-selection
66+ Configurable<double > cMinV0NegDCArToPVcut{" cMinV0NegDCArToPVcut" , 0 .05f , " V0 Negative Track DCAr cut to PV Minimum" }; // Pre-selection
67+ // DCAz to PV
68+ Configurable<double > cMaxDCAzToPVcut{" cMaxDCAzToPVcut" , 2.0 , " Track DCAz cut to PV Maximum" };
69+ Configurable<double > cMinDCAzToPVcut{" cMinDCAzToPVcut" , 0.0 , " Track DCAz cut to PV Minimum" };
70+
71+ Configurable<double > cMinV0Radius{" cMinV0Radius" , 5.0 , " Minimum V0 radius from PV" };
72+ Configurable<double > cMaxV0Radius{" cMaxV0Radius" , 200.0 , " Maximum V0 radius from PV" };
73+ Configurable<double > cMinV0CosPA{" cMinV0CosPA" , 0.995 , " Minimum V0 CosPA to PV" };
74+
75+ HistogramRegistry qaRegistry{" QAHistos" , {
76+ {" hGoodTrackIndices" , " hGoodTrackIndices" , {HistType::kTH1F , {{4 , 0 .0f , 4 .0f }}}},
77+ {" hGoodV0Indices" , " hGoodV0Indices" , {HistType::kTH1F , {{5 , 0 .0f , 5 .0f }}}},
78+ },
79+ OutputObjHandlingPolicy::QAObject};
80+
81+ // Pre-filters for efficient process
82+ // Filter tofPIDFilter = aod::track::tofExpMom < 0.f || ((aod::track::tofExpMom > 0.f) && ((nabs(aod::pidtof::tofNSigmaPi) < pidnSigmaPreSelectionCut) || (nabs(aod::pidtof::tofNSigmaKa) < pidnSigmaPreSelectionCut) || (nabs(aod::pidtof::tofNSigmaPr) < pidnSigmaPreSelectionCut))); // TOF
83+ Filter tpcPIDFilter = nabs(aod::pidtpc::tpcNSigmaPi) < pidnSigmaPreSelectionCut || nabs(aod::pidtpc::tpcNSigmaKa) < pidnSigmaPreSelectionCut || nabs(aod::pidtpc::tpcNSigmaPr) < pidnSigmaPreSelectionCut; // TPC
84+ Filter trackFilter = nabs(aod::track::eta) < cfgCutEta; // Eta cut
85+ Filter trackCutFilter = requireGlobalTrackInFilter(); // Global track cuts
86+
87+ void init (InitContext&)
88+ {
89+ colCuts.setCuts (ConfEvtZvtx, ConfEvtTriggerCheck, ConfEvtTriggerSel, ConfEvtOfflineCheck, ConfIsRun3);
90+ colCuts.init (&qaRegistry);
91+ }
92+
93+ void process (const soa::Join<o2::aod::Collisions, o2::aod::EvSels, aod::Mults>::iterator& collision,
94+ soa::Filtered<aod::Reso2TracksPIDExt> const & tracks, o2::aod::V0Datas const & V0s, aod::BCsWithTimestamps const &)
95+ {
96+ auto bc = collision.bc_as <aod::BCsWithTimestamps>(); // / adding timestamp to access magnetic field later
97+ // Default event selection
98+ if (!colCuts.isSelected (collision))
99+ return ;
100+ colCuts.fillQA (collision);
101+
102+ if (ConfIsRun3) {
103+ resoCollisions (collision.posX (), collision.posY (), collision.posZ (), collision.multFT0M (), colCuts.computeSphericity (collision, tracks), bc.timestamp ());
104+ } else {
105+ resoCollisions (collision.posX (), collision.posY (), collision.posZ (), collision.multFV0M (), colCuts.computeSphericity (collision, tracks), bc.timestamp ());
106+ }
107+
108+ int childIDs[2 ] = {0 , 0 }; // these IDs are necessary to keep track of the children
109+ // Loop over tracks
110+ for (auto & track : tracks) {
111+ // Tracks are already filtered by the pre-filters
112+ qaRegistry.fill (HIST (" hGoodTrackIndices" ), 0.5 );
113+
114+ // Add PID selection criteria here
115+ uint8_t tpcPIDselections = 0 ;
116+ uint8_t tofPIDselections = 0 ;
117+ // TPC PID
118+ if (std::abs (track.tpcNSigmaPi ()) < pidnSigmaPreSelectionCut)
119+ tpcPIDselections |= aod::resodaughter::PDGtype::kPion ;
120+ if (std::abs (track.tpcNSigmaKa ()) < pidnSigmaPreSelectionCut)
121+ tpcPIDselections |= aod::resodaughter::PDGtype::kKaon ;
122+ if (std::abs (track.tpcNSigmaPr ()) < pidnSigmaPreSelectionCut)
123+ tpcPIDselections |= aod::resodaughter::PDGtype::kProton ;
124+ // TOF PID
125+ if (track.hasTOF ()) {
126+ tofPIDselections |= aod::resodaughter::PDGtype::kHasTOF ;
127+ if (std::abs (track.tofNSigmaPi ()) < pidnSigmaPreSelectionCut)
128+ tofPIDselections |= aod::resodaughter::PDGtype::kPion ;
129+ if (std::abs (track.tofNSigmaKa ()) < pidnSigmaPreSelectionCut)
130+ tofPIDselections |= aod::resodaughter::PDGtype::kKaon ;
131+ if (std::abs (track.tofNSigmaPr ()) < pidnSigmaPreSelectionCut)
132+ tofPIDselections |= aod::resodaughter::PDGtype::kProton ;
133+ }
134+
135+ reso2tracks (resoCollisions.lastIndex (),
136+ track.pt (),
137+ track.px (),
138+ track.py (),
139+ track.pz (),
140+ track.eta (),
141+ track.phi (),
142+ aod::resodaughter::DaughterType::kTrack ,
143+ track.dcaXY (),
144+ childIDs,
145+ track.sign (),
146+ (uint8_t )track.tpcNClsCrossedRows (),
147+ track.dcaXY (),
148+ track.dcaZ (),
149+ track.x (),
150+ track.alpha (),
151+ tpcPIDselections,
152+ tofPIDselections,
153+ track.tpcNSigmaPi (),
154+ track.tpcNSigmaKa (),
155+ track.tpcNSigmaPr (),
156+ track.tofNSigmaPi (),
157+ track.tofNSigmaKa (),
158+ track.tofNSigmaPr (),
159+ 0 , 0 , 0 ,
160+ 0 , 0 , 0 , 0 );
161+ }
162+ // / V0s
163+ if (ConfStoreV0) {
164+ for (auto & v0 : V0s) {
165+ qaRegistry.fill (HIST (" hGoodV0Indices" ), 0.5 );
166+ auto postrack = v0.posTrack_as <aod::Reso2TracksPIDExt>();
167+ auto negtrack = v0.negTrack_as <aod::Reso2TracksPIDExt>();
168+
169+ if (postrack.tpcNClsCrossedRows () < mincrossedrows)
170+ continue ;
171+ if (negtrack.tpcNClsCrossedRows () < mincrossedrows)
172+ continue ;
173+ qaRegistry.fill (HIST (" hGoodV0Indices" ), 1.5 );
174+
175+ if (fabs (postrack.dcaXY ()) < cMinV0PosDCArToPVcut)
176+ continue ;
177+ if (fabs (negtrack.dcaXY ()) < cMinV0NegDCArToPVcut)
178+ continue ;
179+ qaRegistry.fill (HIST (" hGoodV0Indices" ), 2.5 );
180+
181+ if ((v0.v0radius () > cMaxV0Radius) || (v0.v0radius () < cMinV0Radius))
182+ continue ;
183+ qaRegistry.fill (HIST (" hGoodV0Indices" ), 3.5 );
184+ if (v0.v0cosPA (collision.posX (), collision.posY (), collision.posZ ()) < cMinV0CosPA)
185+ continue ;
186+ qaRegistry.fill (HIST (" hGoodV0Indices" ), 4.5 );
187+ childIDs[0 ] = v0.posTrackId ();
188+ childIDs[1 ] = v0.negTrackId ();
189+ reso2tracks (resoCollisions.lastIndex (),
190+ v0.pt (),
191+ v0.px (),
192+ v0.py (),
193+ v0.pz (),
194+ v0.eta (),
195+ v0.phi (),
196+ aod::resodaughter::DaughterType::kV0 ,
197+ v0.v0cosPA (collision.posX (), collision.posY (), collision.posZ ()),
198+ childIDs,
199+ 0 ,
200+ 0 ,
201+ v0.v0cosPA (collision.posX (), collision.posY (), collision.posZ ()),
202+ 0 ,
203+ v0.x (), 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
204+ v0.dcaV0daughters (), v0.mLambda (), v0.mAntiLambda (),
205+ v0.v0radius (), v0.x (), v0.y (), v0.z ());
206+ }
207+ }
208+ }
209+ };
210+
211+ WorkflowSpec defineDataProcessing (ConfigContext const & cfgc)
212+ {
213+ return WorkflowSpec{
214+ adaptAnalysisTask<reso2initializer>(cfgc, TaskName{" lf-reso2initializer" }),
215+ };
216+ }
0 commit comments