2020#include " PWGEM/PhotonMeson/DataModel/gammaTables.h"
2121
2222#include < Framework/ASoA.h>
23+ #include < Framework/HistogramRegistry.h>
2324
2425#include < TNamed.h>
2526
@@ -92,7 +93,7 @@ class EMCPhotonCut : public TNamed
9293 EMCPhotonCut () = default ;
9394 EMCPhotonCut (const char * name, const char * title) : TNamed(name, title) {}
9495
95- enum class EMCPhotonCuts : int {
96+ enum class EMCPhotonCuts : std:: uint8_t {
9697 // cluster cut
9798 kDefinition = 0 ,
9899 kEnergy ,
@@ -105,6 +106,12 @@ class EMCPhotonCut : public TNamed
105106 kNCuts
106107 };
107108
109+ enum class TrackType : std::uint8_t {
110+ // cluster cut
111+ kPrimary = 0 ,
112+ kSecondary ,
113+ };
114+
108115 static const char * mCutNames [static_cast <int >(EMCPhotonCuts::kNCuts )];
109116
110117 constexpr auto getClusterId (o2::soa::is_iterator auto const & t) const
@@ -126,7 +133,7 @@ class EMCPhotonCut : public TNamed
126133 // / \param GetPhiCut lambda to get the phi cut value
127134 // / \param applyEoverP bool to check if E/p should be checked (for secondaries we do not check this!)
128135 bool checkTrackMatching (o2::soa::is_iterator auto const & cluster, IsTrackIterator auto & emcmatchedtrack, o2::soa::RowViewSentinel const emcmatchedtrackEnd,
129- bool applyEoverP, auto GetEtaCut, auto GetPhiCut) const
136+ bool applyEoverP, auto GetEtaCut, auto GetPhiCut, o2::framework::HistogramRegistry* fRegistry = nullptr , TrackType trackType = TrackType:: kPrimary ) const
130137 {
131138 // advance to cluster
132139 while (emcmatchedtrack != emcmatchedtrackEnd && getClusterId (emcmatchedtrack) < cluster.globalIndex ()) {
@@ -150,29 +157,137 @@ class EMCPhotonCut : public TNamed
150157 (dPhi > GetPhiCut (trackpt)) ||
151158 (applyEoverP && cluster.e () / trackp >= mMinEoverP );
152159 if (!fail) {
160+ if (mDoQA && fRegistry != nullptr ) {
161+ switch (trackType) {
162+ case TrackType::kPrimary :
163+ fRegistry ->fill (HIST (" Cluster/hTrackdEtadPhi" ), dEta, dPhi);
164+ fRegistry ->fill (HIST (" Cluster/hTrackdEtaPt" ), dEta, trackpt);
165+ fRegistry ->fill (HIST (" Cluster/hTrackdPhiPt" ), dPhi, trackpt);
166+ break ;
167+ case TrackType::kSecondary :
168+ fRegistry ->fill (HIST (" Cluster/hSecTrackdEtadPhi" ), dEta, dPhi);
169+ fRegistry ->fill (HIST (" Cluster/hSecTrackdEtaPt" ), dEta, trackpt);
170+ fRegistry ->fill (HIST (" Cluster/hSecTrackdPhiPt" ), dPhi, trackpt);
171+ break ;
172+ default :
173+ break ;
174+ }
175+ }
153176 return false ; // cluster got a track matche to it
154177 }
155178 ++emcmatchedtrack;
156179 }
157180 return true ; // all tracks checked, cluster survives
158181 }
159182
183+ void fillBeforeClusterHistogram (o2::soa::is_iterator auto const & cluster, o2::framework::HistogramRegistry* fRegistry = nullptr )
184+ {
185+
186+ if (mDoQA == false || fRegistry == nullptr ) {
187+ return ;
188+ }
189+
190+ fRegistry ->fill (HIST (" Cluster/hClusterQualityCuts" ), 0 , cluster.e ());
191+ fRegistry ->fill (HIST (" Cluster/before/hE" ), 0 , cluster.e ());
192+ fRegistry ->fill (HIST (" Cluster/before/hPt" ), 0 , cluster.pt ());
193+ fRegistry ->fill (HIST (" Cluster/before/hEtaPhi" ), 0 , cluster.eta (), cluster.phi ());
194+ fRegistry ->fill (HIST (" Cluster/before/hNCell" ), 0 , cluster.nCells (), cluster.e ());
195+ fRegistry ->fill (HIST (" Cluster/before/hM02" ), 0 , cluster.m02 (), cluster.e ());
196+ fRegistry ->fill (HIST (" Cluster/before/hTime" ), 0 , cluster.time (), cluster.e ());
197+ }
198+
199+ void fillAfterClusterHistogram (o2::soa::is_iterator auto const & cluster, o2::framework::HistogramRegistry* fRegistry = nullptr )
200+ {
201+
202+ if (mDoQA == false || fRegistry == nullptr ) {
203+ return ;
204+ }
205+
206+ fRegistry ->fill (HIST (" Cluster/hClusterQualityCuts" ), 0 , cluster.e ());
207+ fRegistry ->fill (HIST (" Cluster/before/hE" ), 0 , cluster.e ());
208+ fRegistry ->fill (HIST (" Cluster/before/hPt" ), 0 , cluster.pt ());
209+ fRegistry ->fill (HIST (" Cluster/before/hEtaPhi" ), 0 , cluster.eta (), cluster.phi ());
210+ fRegistry ->fill (HIST (" Cluster/before/hNCell" ), 0 , cluster.nCells (), cluster.e ());
211+ fRegistry ->fill (HIST (" Cluster/before/hM02" ), 0 , cluster.m02 (), cluster.e ());
212+ fRegistry ->fill (HIST (" Cluster/before/hTime" ), 0 , cluster.time (), cluster.e ());
213+ }
214+
160215 // / \brief check if given clusters survives all cuts
161216 // / \param flags EMBitFlags where results will be stored
162217 // / \param cluster cluster table to check
163218 // / \param matchedTracks matched primary tracks table
164219 // / \param matchedSecondaries matched secondary tracks table
165- void AreSelectedRunning (EMBitFlags& flags, o2::soa::is_table auto const & clusters, IsTrackContainer auto const & emcmatchedtracks, IsTrackContainer auto const & secondaries) const
220+ // / \param fRegistry HistogramRegistry pointer of the main task
221+ void AreSelectedRunning (EMBitFlags& flags, o2::soa::is_table auto const & clusters, IsTrackContainer auto const & emcmatchedtracks, IsTrackContainer auto const & secondaries, o2::framework::HistogramRegistry* fRegistry = nullptr )
166222 {
167223 auto emcmatchedtrackIter = emcmatchedtracks.begin ();
168224 auto emcmatchedtrackEnd = emcmatchedtracks.end ();
169225 auto secondaryIter = secondaries.begin ();
170226 auto secondaryEnd = secondaries.end ();
171227 size_t iCluster = 0 ;
228+
229+ // Check if we want to do QA and provided proper histogram registry
230+ if (mDoQA && fRegistry != nullptr ) {
231+ const o2::framework::AxisSpec thAxisClusterEnergy{500 , 0 , 50 , " #it{E}_{cls} (GeV)" };
232+ const o2::framework::AxisSpec thAxisMomentum{250 , 0 ., 25 ., " #it{p}_{T} (GeV/#it{c})" };
233+ const o2::framework::AxisSpec thAxisDEta{200 , -0.1 , 0.1 , " #Delta#eta" };
234+ const o2::framework::AxisSpec thAxisDPhi{200 , -0.1 , 0.1 , " #Delta#varphi (rad)" };
235+ const o2::framework::AxisSpec thAxisEnergy{500 , 0 ., 50 ., " #it{E} (GeV)" };
236+ const o2::framework::AxisSpec thAxisEta{320 , -0.8 , 0.8 , " #eta" };
237+ const o2::framework::AxisSpec thAxisPhi{500 , 0 , o2::constants::math::TwoPI, " #varphi (rad)" };
238+ const o2::framework::AxisSpec thAxisNCell{51 , -0.5 , 50.5 , " #it{N}_{cell}" };
239+ const o2::framework::AxisSpec thAxisM02{200 , 0 , 2.0 , " #it{M}_{02}" };
240+ const o2::framework::AxisSpec thAxisTime{300 , -150 , +150 , " #it{t}_{cls} (ns)" };
241+ const o2::framework::AxisSpec thAxisEoverP{400 , 0 , 10 ., " #it{E}_{cls}/#it{p}_{track} (#it{c})" };
242+
243+ fRegistry ->add (" Cluster/before/hE" , " E_{cluster};#it{E}_{cluster} (GeV);#it{N}_{cluster}" , o2::framework::kTH1F , {thAxisClusterEnergy}, true );
244+ fRegistry ->add (" Cluster/before/hPt" , " Transverse momenta of clusters;#it{p}_{T} (GeV/c);#it{N}_{cluster}" , o2::framework::kTH1F , {thAxisClusterEnergy}, true );
245+ fRegistry ->add (" Cluster/before/hNgamma" , " Number of #gamma candidates per collision;#it{N}_{#gamma} per collision;#it{N}_{collisions}" , o2::framework::kTH1F , {{1001 , -0 .5f , 1000 .5f }}, true );
246+ fRegistry ->add (" Cluster/before/hEtaPhi" , " #eta vs #varphi;#eta;#varphi (rad.)" , o2::framework::kTH2F , {thAxisEta, thAxisPhi}, true );
247+ fRegistry ->add (" Cluster/before/hNCell" , " #it{N}_{cells};N_{cells} (GeV);#it{E}_{cluster} (GeV)" , o2::framework::kTH2F , {thAxisNCell, thAxisClusterEnergy}, true );
248+ fRegistry ->add (" Cluster/before/hM02" , " Long ellipse axis;#it{M}_{02} (cm);#it{E}_{cluster} (GeV)" , o2::framework::kTH2F , {thAxisM02, thAxisClusterEnergy}, true );
249+ fRegistry ->add (" Cluster/before/hTime" , " Cluster time;#it{t}_{cls} (ns);#it{E}_{cluster} (GeV)" , o2::framework::kTH2F , {thAxisTime, thAxisClusterEnergy}, true );
250+
251+ fRegistry ->addClone (" Cluster/before/" , " Cluster/after/" );
252+
253+ auto hClusterQualityCuts = fRegistry ->add <TH2>(" Cluster/hClusterQualityCuts" , " Energy at which clusters are removed by a given cut;;#it{E} (GeV)" , o2::framework::kTH2F , {{static_cast <int >(EMCPhotonCut::EMCPhotonCuts::kNCuts ) + 2 , -0.5 , static_cast <double >(EMCPhotonCut::EMCPhotonCuts::kNCuts ) + 1.5 }, thAxisClusterEnergy}, true );
254+ hClusterQualityCuts->GetXaxis ()->SetBinLabel (1 , " In" );
255+ hClusterQualityCuts->GetXaxis ()->SetBinLabel (2 , " Definition" );
256+ hClusterQualityCuts->GetXaxis ()->SetBinLabel (3 , " Energy" );
257+ hClusterQualityCuts->GetXaxis ()->SetBinLabel (4 , " NCell" );
258+ hClusterQualityCuts->GetXaxis ()->SetBinLabel (5 , " M02" );
259+ hClusterQualityCuts->GetXaxis ()->SetBinLabel (6 , " Timing" );
260+ hClusterQualityCuts->GetXaxis ()->SetBinLabel (7 , " TM" );
261+ hClusterQualityCuts->GetXaxis ()->SetBinLabel (8 , " Sec. TM" );
262+ hClusterQualityCuts->GetXaxis ()->SetBinLabel (9 , " Exotic" );
263+ hClusterQualityCuts->GetXaxis ()->SetBinLabel (10 , " Out" );
264+
265+ fRegistry ->add (" Cluster/hTrackdEtadPhi" , " d#eta vs. d#varphi of matched tracks;d#eta;d#varphi (rad.)" , o2::framework::kTH2F , {thAxisDEta, thAxisDPhi}, true );
266+ fRegistry ->add (" Cluster/hTrackdEtaPt" , " d#eta vs. track pT of matched tracks;d#eta;d#varphi (rad.)" , o2::framework::kTH2F , {thAxisDEta, thAxisMomentum}, true );
267+ fRegistry ->add (" Cluster/hTrackdPhiPt" , " d#varphi vs. track pT of matched tracks;d#eta;d#varphi (rad.)" , o2::framework::kTH2F , {thAxisDPhi, thAxisMomentum}, true );
268+ fRegistry ->add (" Cluster/hSecTrackdEtadPhi" , " d#eta vs. d#varphi of matched secondary tracks;d#eta;d#varphi (rad.)" , o2::framework::kTH2F , {thAxisDEta, thAxisDPhi}, true );
269+ fRegistry ->add (" Cluster/hSecTrackdEtaPt" , " d#eta vs. track pT of matched secondary tracks;d#eta;d#varphi (rad.)" , o2::framework::kTH2F , {thAxisDEta, thAxisMomentum}, true );
270+ fRegistry ->add (" Cluster/hSecTrackdPhiPt" , " d#varphi vs. track pT of matched secondary tracks;d#eta;d#varphi (rad.)" , o2::framework::kTH2F , {thAxisDPhi, thAxisMomentum}, true );
271+ }
272+
273+ nTotClusterPerColl = 0 ;
274+ currentCollID = clusters.iteratorAt (0 ).emeventId ();
172275 for (const auto & cluster : clusters) {
276+ if (currentCollID == cluster.emeventId ()) {
277+ ++nTotClusterPerColl;
278+ } else {
279+ fRegistry ->fill (HIST (" Cluster/before/hNgamma" ), nTotClusterPerColl);
280+ nTotClusterPerColl = 0 ;
281+ }
282+ if (mDoQA == true || fRegistry != nullptr ) {
283+ fillBeforeClusterHistogram (cluster, fRegistry );
284+ }
173285 if (!IsSelectedRunning (cluster, emcmatchedtrackIter, emcmatchedtrackEnd, secondaryIter, secondaryEnd)) {
174286 flags.set (iCluster);
287+ } else if (mDoQA == true || fRegistry != nullptr ) {
288+ fillAfterClusterHistogram (cluster, fRegistry );
175289 }
290+ currentCollID = cluster.emeventId ();
176291 ++iCluster;
177292 }
178293 }
@@ -184,32 +299,47 @@ class EMCPhotonCut : public TNamed
184299 // / \param secondaryIter current iterator of matched secondary tracks
185300 // / \param secondaryEnd end iterator of matched secondary tracks
186301 // / \return true if cluster survives all cuts else false
187- bool IsSelectedRunning (o2::soa::is_iterator auto const & cluster, IsTrackIterator auto & emcmatchedtrackIter, o2::soa::RowViewSentinel const emcmatchedtrackEnd, IsTrackIterator auto & secondaryIter, o2::soa::RowViewSentinel const secondaryEnd) const
302+ bool IsSelectedRunning (o2::soa::is_iterator auto const & cluster, IsTrackIterator auto & emcmatchedtrackIter, o2::soa::RowViewSentinel const emcmatchedtrackEnd, IsTrackIterator auto & secondaryIter, o2::soa::RowViewSentinel const secondaryEnd, o2::framework::HistogramRegistry* fRegistry = nullptr )
188303 {
189304 if (!IsSelectedEMCalRunning (EMCPhotonCuts::kDefinition , cluster)) {
305+ fRegistry ->fill (HIST (" Cluster/hClusterQualityCuts" ), static_cast <int >(EMCPhotonCuts::kDefinition ) + 1 , cluster.e ());
190306 return false ;
191307 }
192308 if (!IsSelectedEMCalRunning (EMCPhotonCuts::kEnergy , cluster)) {
309+ fRegistry ->fill (HIST (" Cluster/hClusterQualityCuts" ), static_cast <int >(EMCPhotonCuts::kEnergy ) + 1 , cluster.e ());
193310 return false ;
194311 }
195312 if (!IsSelectedEMCalRunning (EMCPhotonCuts::kNCell , cluster)) {
313+ fRegistry ->fill (HIST (" Cluster/hClusterQualityCuts" ), static_cast <int >(EMCPhotonCuts::kNCell ) + 1 , cluster.e ());
196314 return false ;
197315 }
198316 if (!IsSelectedEMCalRunning (EMCPhotonCuts::kM02 , cluster)) {
317+ fRegistry ->fill (HIST (" Cluster/hClusterQualityCuts" ), static_cast <int >(EMCPhotonCuts::kM02 ) + 1 , cluster.e ());
199318 return false ;
200319 }
201320 if (!IsSelectedEMCalRunning (EMCPhotonCuts::kTiming , cluster)) {
321+ fRegistry ->fill (HIST (" Cluster/hClusterQualityCuts" ), static_cast <int >(EMCPhotonCuts::kTiming ) + 1 , cluster.e ());
202322 return false ;
203323 }
204324 if (mUseTM && (!IsSelectedEMCalRunning (EMCPhotonCuts::kTM , cluster, emcmatchedtrackIter, emcmatchedtrackEnd))) {
325+ fRegistry ->fill (HIST (" Cluster/hClusterQualityCuts" ), static_cast <int >(EMCPhotonCuts::kTM ) + 1 , cluster.e ());
205326 return false ;
206327 }
207328 if (mUseSecondaryTM && (!IsSelectedEMCalRunning (EMCPhotonCuts::kSecondaryTM , cluster, secondaryIter, secondaryEnd))) {
329+ fRegistry ->fill (HIST (" Cluster/hClusterQualityCuts" ), static_cast <int >(EMCPhotonCuts::kSecondaryTM ) + 1 , cluster.e ());
208330 return false ;
209331 }
210332 if (!IsSelectedEMCalRunning (EMCPhotonCuts::kExotic , cluster)) {
333+ fRegistry ->fill (HIST (" Cluster/hClusterQualityCuts" ), static_cast <int >(EMCPhotonCuts::kExotic ) + 1 , cluster.e ());
211334 return false ;
212335 }
336+ fRegistry ->fill (HIST (" Cluster/hClusterQualityCuts" ), static_cast <int >(EMCPhotonCuts::kNCuts ) + 1 , cluster.e ());
337+ if (currentCollID == cluster.emeventId ()) {
338+ ++nAccClusterPerColl;
339+ } else {
340+ fRegistry ->fill (HIST (" Cluster/before/hNgamma" ), nAccClusterPerColl);
341+ nAccClusterPerColl = 0 ;
342+ }
213343 return true ;
214344 }
215345
@@ -439,6 +569,10 @@ class EMCPhotonCut : public TNamed
439569 // / \param flag flag to use secondary track matching
440570 void SetUseSecondaryTM (bool flag = false );
441571
572+ // / \brief Set flag to do QA
573+ // / \param flag flag to do QA
574+ void SetDoQA (bool flag = false );
575+
442576 // / \brief Set parameters for track matching delta eta = a + (pT + b)^c
443577 // / \param a a in a + (pT + b)^c
444578 // / \param b b in a + (pT + b)^c
@@ -517,8 +651,13 @@ class EMCPhotonCut : public TNamed
517651 float mMaxTime {25 .f }; // /< maximum cluster timing
518652 float mMinEoverP {1 .75f }; // /< minimum cluster energy over track momentum ratio needed for the pair to be considered matched
519653 bool mUseExoticCut {true }; // /< flag to decide if the exotic cluster cut is to be checked or not
520- bool mUseTM {true }; // /< flag to decide if track matching cut is to be checek or not
521- bool mUseSecondaryTM {false }; // /< flag to decide if seconary track matching cut is to be checek or not
654+ bool mUseTM {true }; // /< flag to decide if track matching cut is to be check or not
655+ bool mUseSecondaryTM {false }; // /< flag to decide if seconary track matching cut is to be check or not
656+ bool mDoQA {false }; // /< flag to decide if QA should be done or not
657+
658+ uint nTotClusterPerColl{0 }; // /< running number of all cluster per collision used for QA
659+ uint nAccClusterPerColl{0 }; // /< running number of accepted cluster per collision used for QA
660+ int currentCollID{-1 }; // /< running collision ID of clusters used for QA
522661
523662 TrackMatchingParams mTrackMatchingEtaParams = {-1 .f , 0 .f , 0 .f };
524663 TrackMatchingParams mTrackMatchingPhiParams = {-1 .f , 0 .f , 0 .f };
0 commit comments